This commit is contained in:
Gabriel Brown 2024-07-19 17:00:36 -05:00
parent 76977427e0
commit 279e0ad2d8
5 changed files with 251 additions and 58 deletions

View File

@ -0,0 +1,18 @@
"use server";
import type { NextApiRequest, NextApiResponse } from 'next';
import { getEmployees } from '~/server/functions';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'GET') {
try {
const employees = await getEmployees();
res.status(200).json(employees);
} catch (error) {
console.error('Error fetching employees:', error);
res.status(500).json({ message: 'Internal server error' });
}
} else {
res.setHeader('Allow', ['GET']);
res.status(405).json({ message: `Method ${req.method} Not Allowed` });
}
}

View File

@ -0,0 +1,29 @@
"use server";
import type { NextApiRequest, NextApiResponse } from 'next';
import { updateEmployeeStatus } from '~/server/functions';
type UpdateStatusBody = {
employeeIds: number[];
newStatus: string;
};
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
const { employeeIds, newStatus } = req.body as UpdateStatusBody;
if (!Array.isArray(employeeIds) || typeof newStatus !== 'string') {
return res.status(400).json({ message: 'Invalid input' });
}
try {
await updateEmployeeStatus(employeeIds, newStatus);
return res.status(200).json({ message: 'Status updated successfully' });
} catch (error) {
console.error('Error updating status:', error);
return res.status(500).json({ message: 'Internal server error' });
}
} else {
res.setHeader('Allow', ['POST']);
return res.status(405).json({ message: `Method ${req.method} Not Allowed` });
}
}

121
src/components/ui/Table.tsx Normal file
View File

@ -0,0 +1,121 @@
'use client';
import { useState, useEffect } from 'react';
// Define the Employee interface to match data fetched on the server
interface Employee {
id: number;
name: string;
status: string;
updatedAt: Date;
}
export default function Table({ employees }: { employees: Employee[] }) {
const [selectedIds, setSelectedIds] = useState<number[]>([]);
const [status, setStatus] = useState('');
const [employeeData, setEmployeeData] = useState(employees);
useEffect(() => {
// Refresh employee data if needed after state updates
setEmployeeData(employees);
}, [employees]);
const handleCheckboxChange = (id: number) => {
setSelectedIds((prevSelected) =>
prevSelected.includes(id)
? prevSelected.filter((prevId) => prevId !== id)
: [...prevSelected, id]
);
};
const handleStatusChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setStatus(e.target.value);
};
const handleSubmit = async () => {
if (selectedIds.length > 0 && status.trim() !== '') {
await fetch('/api/update_status', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.API_KEY}`
},
body: JSON.stringify({ employeeIds: selectedIds, newStatus: status }),
});
// Optionally refresh data on the client-side after update
const updatedEmployees = await fetchEmployees();
setEmployeeData(updatedEmployees);
setSelectedIds([]);
setStatus('');
}
};
const fetchEmployees = async (): Promise<Employee[]> => {
const res = await fetch('/api/get_employees', {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.API_KEY}`
}
});
return res.json() as Promise<Employee[]>;
};
const formatTime = (timestamp: Date) => {
const date = new Date(timestamp);
const time = date.toLocaleTimeString('en-US', {
hour: 'numeric',
minute: 'numeric',
});
const day = date.getDate();
const month = date.toLocaleString('default', { month: 'long' });
return `${time} - ${month} ${day}`;
};
return (
<div>
<table className="w-5/6 m-auto text-center border-collapse text-[42px]">
<thead className="bg-gradient-to-br from-[#212121] to-[#333333]">
<tr>
<th className="p-5 border border-[#3e4446] text-[48px]" />
<th className="p-2 border border-[#3e4446] text-[48px]">Name</th>
<th className="p-2 border border-[#3e4446] text-[48px]">Status</th>
<th className="p-2 border border-[#3e4446] text-[48px]">Updated At</th>
</tr>
</thead>
<tbody>
{employeeData.map((employee) => (
<tr className="even:bg-gradient-to-bl from-[#222222] to-[#232323]" key={employee.id}>
<td className="p-1 border border-[#3e4446]">
<input
type="checkbox"
className="m-0 cursor-pointer transform scale-150"
checked={selectedIds.includes(employee.id)}
onChange={() => handleCheckboxChange(employee.id)}
/>
</td>
<td className="p-1 border border-[#3e4446]">{employee.name}</td>
<td className="p-1 border border-[#3e4446]">{employee.status}</td>
<td className="p-1 border border-[#3e4446]">{formatTime(employee.updatedAt)}</td>
</tr>
))}
</tbody>
</table>
<div className="m-auto flex flex-row items-center justify-center">
<input
type="text"
placeholder="New Status"
className="w-1/5 p-2 border-none rounded-md"
value={status}
onChange={handleStatusChange}
/>
<button
type="submit"
className="m-2 px-2 py-5 border-none rounded-md text-center bg-gradient-to-br from-[#484848] to-[#333333]"
onClick={handleSubmit}
>
Update
</button>
</div>
</div>
);
}

View File

@ -1,67 +1,70 @@
//import { auth } from "~/auth";
import { getEmployees } from "~/server/functions";
import Table from "~/components/ui/Table";
export const dynamic = "force-dynamic";
//export const dynamic = "force-dynamic";
export default async function Techs_Table() {
const employees = await getEmployees();
return <Table employees={employees} />;
};
const formatTime = (timestamp: Date) => {
const date = new Date(timestamp);
const time = date.toLocaleTimeString("en-US",
{hour: "numeric", minute: "numeric",});
const day = date.getDate();
const month = date.toLocaleString("default", { month: "long" });
return `${time} - ${month} ${day}`;
}
//const formatTime = (timestamp: Date) => {
//const date = new Date(timestamp);
//const time = date.toLocaleTimeString("en-US",
//{hour: "numeric", minute: "numeric",});
//const day = date.getDate();
//const month = date.toLocaleString("default", { month: "long" });
//return `${time} - ${month} ${day}`;
//}
//const session = await auth();
//const users_name = session?.user?.name;
return (
<div>
<table className="w-5/6 m-auto text-center border-collapse text-[42px]">
<thead className="bg-gradient-to-br from-[#212121] to-[#333333]">
<tr>
<th className="p-5 border border-[#3e4446] text-[48px]"/>
<th className="p-2 border border-[#3e4446] text-[48px]">
Name
</th>
<th className="p-2 border border-[#3e4446] text-[48px]">
Status
</th>
<th className="p-2 border border-[#3e4446] text-[48px]">
Updated At
</th>
</tr>
</thead>
<tbody>
{employees.map((employee) => (
<tr className="even:bg-gradient-to-bl from-[#222222] to-[#232323]" key={employee.id}>
<td className="p-1 border border-[#3e4446]">
<input type="checkbox"
className="m-0 cursor-pointer transform scale-150"
//checked={}
/>
</td>
<td className="p-1 border border-[#3e4446]">{employee.name}</td>
<td className="p-1 border border-[#3e4446]">{employee.status}</td>
<td className="p-1 border border-[#3e4446]">{formatTime(employee.updatedAt)}</td>
</tr>
))}
</tbody>
</table>
<div className="m-auto flex flex-row items-center justify-center">
<input type="text" placeholder="New Status"
className="w-1/5 p-2 border-none rounded-md"
//value={}
/>
<button type="submit"
className="m-2 px-2 py-5 border-none rounded-md text-center bg-gradient-to-br from-[#484848] to-[#333333]"
>
Update
</button>
</div>
</div>
);
};
//return (
//<div>
//<table className="w-5/6 m-auto text-center border-collapse text-[42px]">
//<thead className="bg-gradient-to-br from-[#121212] to-[#333333]">
//<tr>
//<th className="p-5 border border-[#3e4446] text-[48px]"/>
//<th className="p-2 border border-[#3e4446] text-[48px]">
//Name
//</th>
//<th className="p-2 border border-[#3e4446] text-[48px]">
//Status
//</th>
//<th className="p-2 border border-[#3e4446] text-[48px]">
//Updated At
//</th>
//</tr>
//</thead>
//<tbody>
//{employees.map((employee) => (
//<tr className="even:bg-gradient-to-bl from-[#222222] to-[#323232]" key={employee.id}>
//<td className="p-1 border border-[#3e4446]">
//<input type="checkbox"
//className="m-0 cursor-pointer transform scale-150"
////checked={}
///>
//</td>
//<td className="p-1 border border-[#3e4446]">{employee.name}</td>
//<td className="p-1 border border-[#3e4446]">{employee.status}</td>
//<td className="p-1 border border-[#3e4446]">{formatTime(employee.updatedAt)}</td>
//</tr>
//))}
//</tbody>
//</table>
//<div className="m-auto flex flex-row items-center justify-center">
//<input type="text" placeholder="New Status"
//className="w-1/5 p-2 border-none rounded-xl"
////value={}
///>
//<button type="submit"
//className="m-2 p-3 border-none rounded-2xl text-center bg-gradient-to-br from-[#484848] to-[#333333]"
//>
//Update
//</button>
//</div>
//</div>
//);
//};

View File

@ -1,11 +1,33 @@
import "server-only";
import { db } from "~/server/db";
//import * as schema from "~/server/db/schema";
import { sql } from "drizzle-orm";
// Function to Get Employees
export const getEmployees = async () => {
return await db.query.users.findMany({
orderBy: (model, { desc }) => desc(model.id),
orderBy: (model, { asc }) => asc(model.id),
});
};
// Function to Update Employee Status using Raw SQL
export const updateEmployeeStatus = async (employeeIds: number[], newStatus: string) => {
try {
// Convert array of ids to a format suitable for SQL query (comma-separated string)
const idString = employeeIds.join(",");
// Prepare the raw SQL query with embedded variables
const query = `
UPDATE users
SET status = '${newStatus}', updatedAt = '${new Date().toISOString()}'
WHERE id IN (${idString})
`;
// Execute the raw SQL query using the execute method
await db.execute(sql`${query}`);
return { success: true };
} catch (error) {
console.error("Error updating employee status:", error);
throw new Error("Failed to update status");
}
};