ugh
This commit is contained in:
parent
76977427e0
commit
279e0ad2d8
18
src/app/api/get_employees.ts
Normal file
18
src/app/api/get_employees.ts
Normal 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` });
|
||||||
|
}
|
||||||
|
}
|
29
src/app/api/update_status.ts
Normal file
29
src/app/api/update_status.ts
Normal 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
121
src/components/ui/Table.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
@ -1,67 +1,70 @@
|
|||||||
//import { auth } from "~/auth";
|
//import { auth } from "~/auth";
|
||||||
import { getEmployees } from "~/server/functions";
|
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() {
|
export default async function Techs_Table() {
|
||||||
|
|
||||||
const employees = await getEmployees();
|
const employees = await getEmployees();
|
||||||
|
return <Table employees={employees} />;
|
||||||
|
};
|
||||||
|
|
||||||
const formatTime = (timestamp: Date) => {
|
//const formatTime = (timestamp: Date) => {
|
||||||
const date = new Date(timestamp);
|
//const date = new Date(timestamp);
|
||||||
const time = date.toLocaleTimeString("en-US",
|
//const time = date.toLocaleTimeString("en-US",
|
||||||
{hour: "numeric", minute: "numeric",});
|
//{hour: "numeric", minute: "numeric",});
|
||||||
const day = date.getDate();
|
//const day = date.getDate();
|
||||||
const month = date.toLocaleString("default", { month: "long" });
|
//const month = date.toLocaleString("default", { month: "long" });
|
||||||
return `${time} - ${month} ${day}`;
|
//return `${time} - ${month} ${day}`;
|
||||||
}
|
//}
|
||||||
//const session = await auth();
|
//const session = await auth();
|
||||||
//const users_name = session?.user?.name;
|
//const users_name = session?.user?.name;
|
||||||
|
|
||||||
return (
|
//return (
|
||||||
<div>
|
//<div>
|
||||||
<table className="w-5/6 m-auto text-center border-collapse text-[42px]">
|
//<table className="w-5/6 m-auto text-center border-collapse text-[42px]">
|
||||||
<thead className="bg-gradient-to-br from-[#212121] to-[#333333]">
|
//<thead className="bg-gradient-to-br from-[#121212] to-[#333333]">
|
||||||
<tr>
|
//<tr>
|
||||||
<th className="p-5 border border-[#3e4446] text-[48px]"/>
|
//<th className="p-5 border border-[#3e4446] text-[48px]"/>
|
||||||
<th className="p-2 border border-[#3e4446] text-[48px]">
|
//<th className="p-2 border border-[#3e4446] text-[48px]">
|
||||||
Name
|
//Name
|
||||||
</th>
|
//</th>
|
||||||
<th className="p-2 border border-[#3e4446] text-[48px]">
|
//<th className="p-2 border border-[#3e4446] text-[48px]">
|
||||||
Status
|
//Status
|
||||||
</th>
|
//</th>
|
||||||
<th className="p-2 border border-[#3e4446] text-[48px]">
|
//<th className="p-2 border border-[#3e4446] text-[48px]">
|
||||||
Updated At
|
//Updated At
|
||||||
</th>
|
//</th>
|
||||||
</tr>
|
//</tr>
|
||||||
</thead>
|
//</thead>
|
||||||
<tbody>
|
//<tbody>
|
||||||
{employees.map((employee) => (
|
//{employees.map((employee) => (
|
||||||
<tr className="even:bg-gradient-to-bl from-[#222222] to-[#232323]" key={employee.id}>
|
//<tr className="even:bg-gradient-to-bl from-[#222222] to-[#323232]" key={employee.id}>
|
||||||
<td className="p-1 border border-[#3e4446]">
|
//<td className="p-1 border border-[#3e4446]">
|
||||||
<input type="checkbox"
|
//<input type="checkbox"
|
||||||
className="m-0 cursor-pointer transform scale-150"
|
//className="m-0 cursor-pointer transform scale-150"
|
||||||
//checked={}
|
////checked={}
|
||||||
/>
|
///>
|
||||||
</td>
|
//</td>
|
||||||
<td className="p-1 border border-[#3e4446]">{employee.name}</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]">{employee.status}</td>
|
||||||
<td className="p-1 border border-[#3e4446]">{formatTime(employee.updatedAt)}</td>
|
//<td className="p-1 border border-[#3e4446]">{formatTime(employee.updatedAt)}</td>
|
||||||
</tr>
|
//</tr>
|
||||||
))}
|
//))}
|
||||||
</tbody>
|
//</tbody>
|
||||||
</table>
|
//</table>
|
||||||
<div className="m-auto flex flex-row items-center justify-center">
|
//<div className="m-auto flex flex-row items-center justify-center">
|
||||||
<input type="text" placeholder="New Status"
|
//<input type="text" placeholder="New Status"
|
||||||
className="w-1/5 p-2 border-none rounded-md"
|
//className="w-1/5 p-2 border-none rounded-xl"
|
||||||
//value={}
|
////value={}
|
||||||
/>
|
///>
|
||||||
<button type="submit"
|
//<button type="submit"
|
||||||
className="m-2 px-2 py-5 border-none rounded-md text-center bg-gradient-to-br from-[#484848] to-[#333333]"
|
//className="m-2 p-3 border-none rounded-2xl text-center bg-gradient-to-br from-[#484848] to-[#333333]"
|
||||||
>
|
//>
|
||||||
Update
|
//Update
|
||||||
</button>
|
//</button>
|
||||||
</div>
|
//</div>
|
||||||
</div>
|
//</div>
|
||||||
);
|
//);
|
||||||
};
|
//};
|
||||||
|
@ -1,11 +1,33 @@
|
|||||||
import "server-only";
|
import "server-only";
|
||||||
import { db } from "~/server/db";
|
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 () => {
|
export const getEmployees = async () => {
|
||||||
return await db.query.users.findMany({
|
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");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user