Add History Drawer & Clean up APIs. Will clean up more when I am home and have updated the iOS app.
This commit is contained in:
parent
ef0a79de21
commit
b4ff2da7f5
@ -1,6 +1,7 @@
|
|||||||
"use server";
|
"use server";
|
||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
import { getEmployees } from '~/server/functions';
|
import { getEmployees } from '~/server/functions';
|
||||||
|
import { auth } from '~/auth';
|
||||||
|
|
||||||
type Technician = {
|
type Technician = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -10,6 +11,8 @@ type Technician = {
|
|||||||
|
|
||||||
export const GET = async (request: Request) => {
|
export const GET = async (request: Request) => {
|
||||||
try {
|
try {
|
||||||
|
const session = await auth();
|
||||||
|
if (!session) {
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
const apiKey = url.searchParams.get('apikey');
|
const apiKey = url.searchParams.get('apikey');
|
||||||
if (apiKey !== process.env.API_KEY)
|
if (apiKey !== process.env.API_KEY)
|
||||||
@ -17,20 +20,21 @@ export const GET = async (request: Request) => {
|
|||||||
{ message: 'Unauthorized' },
|
{ message: 'Unauthorized' },
|
||||||
{ status: 401 }
|
{ status: 401 }
|
||||||
);
|
);
|
||||||
|
else {
|
||||||
const employees = await getEmployees();
|
const employees = await getEmployees();
|
||||||
// Necessary because I haven't updated the iOS app
|
|
||||||
// yet to expect updatedAt rather than time
|
|
||||||
const formattedEmployees = employees.map((employee: Technician) => ({
|
const formattedEmployees = employees.map((employee: Technician) => ({
|
||||||
name: employee.name,
|
name: employee.name,
|
||||||
status: employee.status,
|
status: employee.status,
|
||||||
time: employee.updatedAt
|
time: employee.updatedAt
|
||||||
}));
|
}));
|
||||||
return NextResponse.json(formattedEmployees, { status: 200 });
|
return NextResponse.json(formattedEmployees, { status: 200 });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const employees = await getEmployees();
|
||||||
|
return NextResponse.json(employees, { status: 200 });
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching employees:', error);
|
console.error('Error fetching employees:', error);
|
||||||
return NextResponse.json(
|
return NextResponse.json({ message: 'Internal server error' }, { status: 500 });
|
||||||
{ message: 'Internal server error' },
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
44
src/app/api/update_status_by_id/route.ts
Normal file
44
src/app/api/update_status_by_id/route.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Update Employee Status by IDs
|
||||||
|
"use server";
|
||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import type { NextRequest } from 'next/server';
|
||||||
|
import { updateEmployeeStatus } from '~/server/functions';
|
||||||
|
import { auth } from '~/auth';
|
||||||
|
|
||||||
|
type UpdateStatusBody = {
|
||||||
|
employeeIds: string[];
|
||||||
|
newStatus: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const POST = async (req: NextRequest) => {
|
||||||
|
const session = await auth();
|
||||||
|
if (!session) {
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const apiKey = url.searchParams.get('apikey');
|
||||||
|
if (apiKey !== process.env.API_KEY)
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: 'Unauthorized' },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const { employeeIds, newStatus } = await req.json() as UpdateStatusBody;
|
||||||
|
if (!Array.isArray(employeeIds) || typeof newStatus !== 'string')
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: 'Invalid input' },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
await updateEmployeeStatus(employeeIds, newStatus);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: 'Status updated successfully' },
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating status:', error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: 'Internal server error' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -1,8 +1,9 @@
|
|||||||
|
// Update Employee Status by Names
|
||||||
"use server";
|
"use server";
|
||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
import { updateEmployeeStatusByName } from '~/server/functions';
|
import { updateEmployeeStatusByName } from '~/server/functions';
|
||||||
|
|
||||||
interface Technician {
|
type Technician = {
|
||||||
name: string;
|
name: string;
|
||||||
status: string;
|
status: string;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
"use server";
|
|
||||||
import { NextResponse } from 'next/server';
|
|
||||||
import { getEmployees } from '~/server/functions';
|
|
||||||
import { auth } from '~/auth';
|
|
||||||
|
|
||||||
export const GET = async () => {
|
|
||||||
try {
|
|
||||||
const session = await auth();
|
|
||||||
if (!session)
|
|
||||||
return NextResponse.json({ message: 'Unauthorized' }, { status: 401 });
|
|
||||||
const employees = await getEmployees();
|
|
||||||
return NextResponse.json(employees, { status: 200 });
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching employees:', error);
|
|
||||||
return NextResponse.json({ message: 'Internal server error' }, { status: 500 });
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,38 +0,0 @@
|
|||||||
"use server";
|
|
||||||
import { NextResponse } from 'next/server';
|
|
||||||
import type { NextRequest } from 'next/server';
|
|
||||||
import { updateEmployeeStatus } from '~/server/functions';
|
|
||||||
import { auth } from '~/auth';
|
|
||||||
|
|
||||||
type UpdateStatusBody = {
|
|
||||||
employeeIds: string[];
|
|
||||||
newStatus: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const POST = async (req: NextRequest) => {
|
|
||||||
const session = await auth();
|
|
||||||
if (!session)
|
|
||||||
return NextResponse.json(
|
|
||||||
{ message: 'Unauthorized' },
|
|
||||||
{ status: 401 }
|
|
||||||
);
|
|
||||||
const { employeeIds, newStatus } = await req.json() as UpdateStatusBody;
|
|
||||||
if (!Array.isArray(employeeIds) || typeof newStatus !== 'string')
|
|
||||||
return NextResponse.json(
|
|
||||||
{ message: 'Invalid input' },
|
|
||||||
{ status: 400 }
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
await updateEmployeeStatus(employeeIds, newStatus);
|
|
||||||
return NextResponse.json(
|
|
||||||
{ message: 'Status updated successfully' },
|
|
||||||
{ status: 200 }
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error updating status:', error);
|
|
||||||
return NextResponse.json(
|
|
||||||
{ message: 'Internal server error' },
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,27 +1,87 @@
|
|||||||
import { Button } from "~/components/ui/shadcn/button";
|
|
||||||
import {
|
import {
|
||||||
Drawer,
|
|
||||||
DrawerClose,
|
DrawerClose,
|
||||||
DrawerContent,
|
DrawerContent,
|
||||||
DrawerDescription,
|
|
||||||
DrawerFooter,
|
DrawerFooter,
|
||||||
DrawerHeader,
|
DrawerHeader,
|
||||||
DrawerTitle,
|
DrawerTitle,
|
||||||
DrawerTrigger,
|
|
||||||
} from "~/components/ui/shadcn/drawer";
|
} from "~/components/ui/shadcn/drawer";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "~/components/ui/shadcn/table";
|
||||||
|
import {
|
||||||
|
Pagination,
|
||||||
|
PaginationContent,
|
||||||
|
PaginationEllipsis,
|
||||||
|
PaginationItem,
|
||||||
|
PaginationLink,
|
||||||
|
PaginationNext,
|
||||||
|
PaginationPrevious,
|
||||||
|
} from "~/components/ui/shadcn/pagination";
|
||||||
|
//import { Button } from "~/components/ui/shadcn/button";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
<Drawer>
|
export default function History_Drawer() {
|
||||||
<DrawerTrigger>Open</DrawerTrigger>
|
//const
|
||||||
|
return (
|
||||||
<DrawerContent>
|
<DrawerContent>
|
||||||
<DrawerHeader>
|
<DrawerHeader>
|
||||||
<DrawerTitle>Are you absolutely sure?</DrawerTitle>
|
<DrawerTitle>
|
||||||
<DrawerDescription>This action cannot be undone.</DrawerDescription>
|
<div className="flex flex-row items-center text-center
|
||||||
|
sm:justify-center sm:ml-0 py-4">
|
||||||
|
<Image src="/images/tech_tracker_logo.png"
|
||||||
|
alt="Tech Tracker Logo" width={60} height={60}
|
||||||
|
className="max-w-[40px] md:max-w-[120px]"
|
||||||
|
/>
|
||||||
|
<h1 className="title-text text-sm md:text-2xl lg:text-6xl
|
||||||
|
bg-gradient-to-r from-[#bec8e6] via-[#F0EEE4] to-[#FFF8E7]
|
||||||
|
font-bold pl-2 md:pl-4 text-transparent bg-clip-text">
|
||||||
|
History
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</DrawerTitle>
|
||||||
</DrawerHeader>
|
</DrawerHeader>
|
||||||
|
<Table className="w-5/6 lg:w-1/2 m-auto"
|
||||||
|
>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead className="">Name</TableHead>
|
||||||
|
<TableHead>Status</TableHead>
|
||||||
|
<TableHead>Updated At</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell className="font-medium">INV001</TableCell>
|
||||||
|
<TableCell>Paid</TableCell>
|
||||||
|
<TableCell>Credit Card</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
<DrawerFooter>
|
<DrawerFooter>
|
||||||
<Button>Submit</Button>
|
<Pagination>
|
||||||
|
<PaginationContent>
|
||||||
|
<PaginationItem>
|
||||||
|
<PaginationPrevious href="#" />
|
||||||
|
</PaginationItem>
|
||||||
|
<PaginationItem>
|
||||||
|
<PaginationLink href="#">1</PaginationLink>
|
||||||
|
</PaginationItem>
|
||||||
|
<PaginationItem>
|
||||||
|
<PaginationEllipsis />
|
||||||
|
</PaginationItem>
|
||||||
|
<PaginationItem>
|
||||||
|
<PaginationNext href="#" />
|
||||||
|
</PaginationItem>
|
||||||
|
</PaginationContent>
|
||||||
|
</Pagination>
|
||||||
<DrawerClose>
|
<DrawerClose>
|
||||||
<Button variant="outline">Cancel</Button>
|
|
||||||
</DrawerClose>
|
</DrawerClose>
|
||||||
</DrawerFooter>
|
</DrawerFooter>
|
||||||
</DrawerContent>
|
</DrawerContent>
|
||||||
</Drawer>
|
);
|
||||||
|
};
|
||||||
|
@ -3,9 +3,10 @@ import { useState, useEffect, useCallback } from 'react';
|
|||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import Loading from "~/components/ui/Loading";
|
import Loading from "~/components/ui/Loading";
|
||||||
import { useTVMode } from "~/components/context/TVModeContext";
|
import { useTVMode } from "~/components/context/TVModeContext";
|
||||||
|
import { Drawer, DrawerTrigger } from "~/components/ui/shadcn/drawer";
|
||||||
|
import History_Drawer from "~/components/ui/History_Drawer";
|
||||||
|
|
||||||
// Define the Employee interface to match data fetched on the server
|
type Employee = {
|
||||||
interface Employee {
|
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
status: string;
|
status: string;
|
||||||
@ -22,7 +23,7 @@ export default function Tech_Table({ employees }: { employees: Employee[] }) {
|
|||||||
const [employeeData, setEmployeeData] = useState(employees);
|
const [employeeData, setEmployeeData] = useState(employees);
|
||||||
|
|
||||||
const fetch_employees = useCallback(async (): Promise<Employee[]> => {
|
const fetch_employees = useCallback(async (): Promise<Employee[]> => {
|
||||||
const res = await fetch('/api/v2/get_employees', {
|
const res = await fetch('/api/technicians', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${process.env.API_KEY}`
|
'Authorization': `Bearer ${process.env.API_KEY}`
|
||||||
@ -35,12 +36,10 @@ export default function Tech_Table({ employees }: { employees: Employee[] }) {
|
|||||||
if (!session) {
|
if (!session) {
|
||||||
alert("You must be signed in to update status.");
|
alert("You must be signed in to update status.");
|
||||||
return;
|
return;
|
||||||
}
|
} else if (selectedIds.length === 0 && employeeStatus.trim() !== '') {
|
||||||
|
|
||||||
if (selectedIds.length === 0 && employeeStatus.trim() !== '') {
|
|
||||||
const cur_user = employees.find(employee => employee.name === session.user?.name);
|
const cur_user = employees.find(employee => employee.name === session.user?.name);
|
||||||
if (cur_user) {
|
if (cur_user) {
|
||||||
await fetch('/api/v2/update_status', {
|
await fetch('/api/update_status_by_id', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -50,7 +49,7 @@ export default function Tech_Table({ employees }: { employees: Employee[] }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (employeeStatus.trim() !== '') {
|
} else if (employeeStatus.trim() !== '') {
|
||||||
await fetch('/api/v2/update_status', {
|
await fetch('/api/update_status_by_id', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -165,9 +164,10 @@ export default function Tech_Table({ employees }: { employees: Employee[] }) {
|
|||||||
)}
|
)}
|
||||||
<th className="border border-[#3e4446] py-3">Name</th>
|
<th className="border border-[#3e4446] py-3">Name</th>
|
||||||
<th className="border border-[#3e4446] py-3">
|
<th className="border border-[#3e4446] py-3">
|
||||||
<button>
|
<Drawer>
|
||||||
Status
|
<DrawerTrigger>Status</DrawerTrigger>
|
||||||
</button>
|
<History_Drawer />
|
||||||
|
</Drawer>
|
||||||
</th>
|
</th>
|
||||||
<th className="border border-[#3e4446] py-3">Updated At</th>
|
<th className="border border-[#3e4446] py-3">Updated At</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
Loading…
Reference in New Issue
Block a user