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:
		@@ -1,6 +1,7 @@
 | 
			
		||||
"use server";
 | 
			
		||||
import { NextResponse } from 'next/server';
 | 
			
		||||
import { getEmployees } from '~/server/functions';
 | 
			
		||||
import { auth } from '~/auth';
 | 
			
		||||
 | 
			
		||||
type Technician = {
 | 
			
		||||
  name: string;
 | 
			
		||||
@@ -10,27 +11,30 @@ type Technician = {
 | 
			
		||||
 | 
			
		||||
export const GET = async (request: Request) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const url = new URL(request.url);
 | 
			
		||||
    const apiKey = url.searchParams.get('apikey');
 | 
			
		||||
    if (apiKey !== process.env.API_KEY)
 | 
			
		||||
      return NextResponse.json(
 | 
			
		||||
        { message: 'Unauthorized' },
 | 
			
		||||
        { status: 401 }
 | 
			
		||||
      );
 | 
			
		||||
    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) => ({
 | 
			
		||||
      name: employee.name,
 | 
			
		||||
      status: employee.status,
 | 
			
		||||
      time: employee.updatedAt
 | 
			
		||||
    }));
 | 
			
		||||
    return NextResponse.json(formattedEmployees, { status: 200 });
 | 
			
		||||
    const session = await auth();
 | 
			
		||||
    if (!session) {
 | 
			
		||||
      const url = new URL(request.url);
 | 
			
		||||
      const apiKey = url.searchParams.get('apikey');
 | 
			
		||||
      if (apiKey !== process.env.API_KEY)
 | 
			
		||||
        return NextResponse.json(
 | 
			
		||||
          { message: 'Unauthorized' },
 | 
			
		||||
          { status: 401 }
 | 
			
		||||
        );
 | 
			
		||||
      else {
 | 
			
		||||
        const employees = await getEmployees();
 | 
			
		||||
        const formattedEmployees = employees.map((employee: Technician) => ({
 | 
			
		||||
          name: employee.name,
 | 
			
		||||
          status: employee.status,
 | 
			
		||||
          time: employee.updatedAt
 | 
			
		||||
        }));
 | 
			
		||||
        return NextResponse.json(formattedEmployees, { status: 200 });
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      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 }
 | 
			
		||||
    );
 | 
			
		||||
    return NextResponse.json({ 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";
 | 
			
		||||
import { NextResponse } from 'next/server';
 | 
			
		||||
import { updateEmployeeStatusByName } from '~/server/functions';
 | 
			
		||||
 | 
			
		||||
interface Technician {
 | 
			
		||||
type Technician = {
 | 
			
		||||
  name: 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 {
 | 
			
		||||
  Drawer,
 | 
			
		||||
  DrawerClose,
 | 
			
		||||
  DrawerContent,
 | 
			
		||||
  DrawerDescription,
 | 
			
		||||
  DrawerFooter,
 | 
			
		||||
  DrawerHeader,
 | 
			
		||||
  DrawerTitle,
 | 
			
		||||
  DrawerTrigger,
 | 
			
		||||
} 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>
 | 
			
		||||
  <DrawerTrigger>Open</DrawerTrigger>
 | 
			
		||||
  <DrawerContent>
 | 
			
		||||
    <DrawerHeader>
 | 
			
		||||
      <DrawerTitle>Are you absolutely sure?</DrawerTitle>
 | 
			
		||||
      <DrawerDescription>This action cannot be undone.</DrawerDescription>
 | 
			
		||||
    </DrawerHeader>
 | 
			
		||||
    <DrawerFooter>
 | 
			
		||||
      <Button>Submit</Button>
 | 
			
		||||
      <DrawerClose>
 | 
			
		||||
        <Button variant="outline">Cancel</Button>
 | 
			
		||||
      </DrawerClose>
 | 
			
		||||
    </DrawerFooter>
 | 
			
		||||
  </DrawerContent>
 | 
			
		||||
</Drawer>
 | 
			
		||||
export default function History_Drawer() {
 | 
			
		||||
  //const 
 | 
			
		||||
  return (
 | 
			
		||||
    <DrawerContent>
 | 
			
		||||
      <DrawerHeader>
 | 
			
		||||
        <DrawerTitle>
 | 
			
		||||
          <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>
 | 
			
		||||
      <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>
 | 
			
		||||
        <Pagination>
 | 
			
		||||
          <PaginationContent>
 | 
			
		||||
            <PaginationItem>
 | 
			
		||||
              <PaginationPrevious href="#" />
 | 
			
		||||
            </PaginationItem>
 | 
			
		||||
            <PaginationItem>
 | 
			
		||||
              <PaginationLink href="#">1</PaginationLink>
 | 
			
		||||
            </PaginationItem>
 | 
			
		||||
            <PaginationItem>
 | 
			
		||||
              <PaginationEllipsis />
 | 
			
		||||
            </PaginationItem>
 | 
			
		||||
            <PaginationItem>
 | 
			
		||||
              <PaginationNext href="#" />
 | 
			
		||||
            </PaginationItem>
 | 
			
		||||
          </PaginationContent>
 | 
			
		||||
        </Pagination>
 | 
			
		||||
        <DrawerClose>
 | 
			
		||||
        </DrawerClose>
 | 
			
		||||
      </DrawerFooter>
 | 
			
		||||
    </DrawerContent>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,10 @@ import { useState, useEffect, useCallback } from 'react';
 | 
			
		||||
import { useSession } from "next-auth/react";
 | 
			
		||||
import Loading from "~/components/ui/Loading";
 | 
			
		||||
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
 | 
			
		||||
interface Employee {
 | 
			
		||||
type Employee = {
 | 
			
		||||
  id: number;
 | 
			
		||||
  name: string;
 | 
			
		||||
  status: string;
 | 
			
		||||
@@ -22,7 +23,7 @@ export default function Tech_Table({ employees }: { employees: Employee[] }) {
 | 
			
		||||
  const [employeeData, setEmployeeData] = useState(employees);
 | 
			
		||||
 | 
			
		||||
  const fetch_employees = useCallback(async (): Promise<Employee[]> => {
 | 
			
		||||
    const res = await fetch('/api/v2/get_employees', {
 | 
			
		||||
    const res = await fetch('/api/technicians', {
 | 
			
		||||
      method: 'GET',
 | 
			
		||||
      headers: {
 | 
			
		||||
        'Authorization': `Bearer ${process.env.API_KEY}`
 | 
			
		||||
@@ -35,12 +36,10 @@ export default function Tech_Table({ employees }: { employees: Employee[] }) {
 | 
			
		||||
    if (!session) {
 | 
			
		||||
      alert("You must be signed in to update status.");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (selectedIds.length === 0 && employeeStatus.trim() !== '') {
 | 
			
		||||
    } else if (selectedIds.length === 0 && employeeStatus.trim() !== '') {
 | 
			
		||||
      const cur_user = employees.find(employee => employee.name === session.user?.name);
 | 
			
		||||
      if (cur_user) {
 | 
			
		||||
        await fetch('/api/v2/update_status', {
 | 
			
		||||
        await fetch('/api/update_status_by_id', {
 | 
			
		||||
          method: 'POST',
 | 
			
		||||
          headers: {
 | 
			
		||||
            'Content-Type': 'application/json',
 | 
			
		||||
@@ -50,7 +49,7 @@ export default function Tech_Table({ employees }: { employees: Employee[] }) {
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    } else if (employeeStatus.trim() !== '') {
 | 
			
		||||
      await fetch('/api/v2/update_status', {
 | 
			
		||||
      await fetch('/api/update_status_by_id', {
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        headers: {
 | 
			
		||||
          '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">
 | 
			
		||||
                <button>
 | 
			
		||||
                  Status
 | 
			
		||||
                </button>
 | 
			
		||||
                <Drawer>
 | 
			
		||||
                  <DrawerTrigger>Status</DrawerTrigger>
 | 
			
		||||
                    <History_Drawer />
 | 
			
		||||
                </Drawer>
 | 
			
		||||
              </th>
 | 
			
		||||
              <th className="border border-[#3e4446] py-3">Updated At</th>
 | 
			
		||||
            </tr>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user