Add legacy APIs so that I can migrate new app to techtracker.gibbyb.com and keep iOS app working
This commit is contained in:
parent
707ab6515c
commit
f1947ccb62
23
src/app/api/history/route.ts
Normal file
23
src/app/api/history/route.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
"use server";
|
||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { legacyGetHistory } from '~/server/functions';
|
||||||
|
|
||||||
|
export const GET = async (request: Request) => {
|
||||||
|
try {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const apiKey = url.searchParams.get('apikey');
|
||||||
|
const page = Number(url.searchParams.get('page')) || 1;
|
||||||
|
|
||||||
|
if (apiKey !== 'zAf4vYVN2pszrK') {
|
||||||
|
return NextResponse.json({ message: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const perPage = 50; // You can adjust the perPage value as needed
|
||||||
|
const historyData = await legacyGetHistory(page, perPage);
|
||||||
|
|
||||||
|
return NextResponse.json(historyData, { status: 200 });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching history data:', error);
|
||||||
|
return NextResponse.json({ message: 'Internal server error' }, { status: 500 });
|
||||||
|
}
|
||||||
|
};
|
33
src/app/api/technicians/route.ts
Normal file
33
src/app/api/technicians/route.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
"use server";
|
||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { legacyGetEmployees } from '~/server/functions';
|
||||||
|
|
||||||
|
type Technician = {
|
||||||
|
name: string;
|
||||||
|
status: string;
|
||||||
|
updatedAt: Date;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GET = async (request: Request) => {
|
||||||
|
try {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const apiKey = url.searchParams.get('apikey');
|
||||||
|
|
||||||
|
if (apiKey !== 'zAf4vYVN2pszrK') {
|
||||||
|
return NextResponse.json({ message: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const employees = await legacyGetEmployees();
|
||||||
|
|
||||||
|
const formattedEmployees = employees.map((employee: Technician) => ({
|
||||||
|
name: employee.name,
|
||||||
|
status: employee.status,
|
||||||
|
time: employee.updatedAt
|
||||||
|
}));
|
||||||
|
|
||||||
|
return NextResponse.json(formattedEmployees, { status: 200 });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching employees:', error);
|
||||||
|
return NextResponse.json({ message: 'Internal server error' }, { status: 500 });
|
||||||
|
}
|
||||||
|
};
|
44
src/app/api/update_technicians/route.ts
Normal file
44
src/app/api/update_technicians/route.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// src/app/api/update_technicians/route.ts
|
||||||
|
|
||||||
|
"use server";
|
||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { legacyUpdateEmployeeStatusByName } from '~/server/functions';
|
||||||
|
|
||||||
|
interface Technician {
|
||||||
|
name: string;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type guard to check if an object is a Technician
|
||||||
|
const isTechnician = (technician: any): technician is Technician => {
|
||||||
|
return typeof technician.name === 'string' && typeof technician.status === 'string';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const POST = async (request: Request) => {
|
||||||
|
try {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const apiKey = url.searchParams.get('apikey');
|
||||||
|
|
||||||
|
if (apiKey !== 'zAf4vYVN2pszrK') {
|
||||||
|
return NextResponse.json({ message: 'Unauthorized' }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { technicians } = await request.json() as { technicians: Technician[] };
|
||||||
|
if (!Array.isArray(technicians) || technicians.length === 0) {
|
||||||
|
return NextResponse.json({ message: 'Invalid input: expecting an array of technicians.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const technician of technicians) {
|
||||||
|
if (!isTechnician(technician)) {
|
||||||
|
return NextResponse.json({ message: 'Invalid input: missing name or status for a technician.' }, { status: 400 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await legacyUpdateEmployeeStatusByName(technicians);
|
||||||
|
|
||||||
|
return NextResponse.json({ message: 'Technicians updated successfully.' }, { status: 200 });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating technicians:', error);
|
||||||
|
return NextResponse.json({ message: 'Internal server error' }, { status: 500 });
|
||||||
|
}
|
||||||
|
};
|
@ -22,7 +22,7 @@ export default function Table({ employees }: { employees: Employee[] }) {
|
|||||||
}, [employees]);
|
}, [employees]);
|
||||||
|
|
||||||
const fetchEmployees = useCallback(async (): Promise<Employee[]> => {
|
const fetchEmployees = useCallback(async (): Promise<Employee[]> => {
|
||||||
const res = await fetch('/api/get_employees', {
|
const res = await fetch('/api/v2/get_employees', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${process.env.API_KEY}`
|
'Authorization': `Bearer ${process.env.API_KEY}`
|
||||||
@ -86,7 +86,7 @@ export default function Table({ employees }: { employees: Employee[] }) {
|
|||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (selectedIds.length > 0 && status.trim() !== '') {
|
if (selectedIds.length > 0 && status.trim() !== '') {
|
||||||
await fetch('/api/update_status', {
|
await fetch('/api/v2/update_status', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
@ -32,3 +32,114 @@ export const updateEmployeeStatus = async (employeeIds: string[], newStatus: str
|
|||||||
throw new Error("Failed to update status");
|
throw new Error("Failed to update status");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Legacy Functions for Legacy API for iOS App
|
||||||
|
|
||||||
|
// Type definitions
|
||||||
|
interface HistoryEntry {
|
||||||
|
name: string;
|
||||||
|
status: string;
|
||||||
|
time: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PaginatedHistory {
|
||||||
|
data: HistoryEntry[];
|
||||||
|
meta: {
|
||||||
|
current_page: number;
|
||||||
|
per_page: number;
|
||||||
|
total_pages: number;
|
||||||
|
total_count: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to Convert Date to UTC
|
||||||
|
const convertToUTC = (date: Date): Date => {
|
||||||
|
const utcDate = new Date(date.setHours(date.getUTCHours() - 15));
|
||||||
|
return utcDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const legacyGetEmployees = async () => {
|
||||||
|
const employees = await db.query.users.findMany({
|
||||||
|
orderBy: (model, { asc }) => asc(model.id),
|
||||||
|
});
|
||||||
|
if (employees.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
for (const employee of employees) {
|
||||||
|
const date = new Date(employee.updatedAt);
|
||||||
|
employee.updatedAt = convertToUTC(date);
|
||||||
|
}
|
||||||
|
return employees;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to Get History Data with Pagination using Raw SQL
|
||||||
|
export const legacyGetHistory = async (page: number, perPage: number): Promise<PaginatedHistory> => {
|
||||||
|
const offset = (page - 1) * perPage;
|
||||||
|
|
||||||
|
// Raw SQL queries
|
||||||
|
const historyQuery = sql`
|
||||||
|
SELECT u.name, h.status, h.updatedAt
|
||||||
|
FROM history h
|
||||||
|
JOIN users u ON h.user_id = u.id
|
||||||
|
ORDER BY h.id DESC
|
||||||
|
LIMIT ${perPage} OFFSET ${offset}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const countQuery = sql`
|
||||||
|
SELECT COUNT(*) AS total_count
|
||||||
|
FROM history
|
||||||
|
`;
|
||||||
|
|
||||||
|
const [historyResults, countResults] = await Promise.all([
|
||||||
|
db.execute(historyQuery),
|
||||||
|
db.execute(countQuery),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Get the results properly as an array of rows
|
||||||
|
const historyRows = historyResults[0] as { name: string, status: string, updatedAt: Date }[];
|
||||||
|
const countRow = countResults[0] as { total_count: number }[];
|
||||||
|
|
||||||
|
const totalCount = countRow[0]?.total_count || 0;
|
||||||
|
const totalPages = Math.ceil(totalCount / perPage);
|
||||||
|
|
||||||
|
// Format and map results
|
||||||
|
const formattedResults: HistoryEntry[] = historyRows.map(row => ({
|
||||||
|
name: row.name,
|
||||||
|
status: row.status,
|
||||||
|
time: convertToUTC(new Date(row.updatedAt)),
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: formattedResults,
|
||||||
|
meta: {
|
||||||
|
current_page: page,
|
||||||
|
per_page: perPage,
|
||||||
|
total_pages: totalPages,
|
||||||
|
total_count: totalCount,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to Update Employee Status by Name using Raw SQL
|
||||||
|
export const legacyUpdateEmployeeStatusByName = async (technicians: { name: string, status: string }[]) => {
|
||||||
|
try {
|
||||||
|
// Prepare and execute the queries for each technician
|
||||||
|
for (const technician of technicians) {
|
||||||
|
const { name, status } = technician;
|
||||||
|
const date = new Date();
|
||||||
|
const utcdate: Date = new Date(date.setHours(date.getUTCHours() - 12));
|
||||||
|
const query = sql`
|
||||||
|
UPDATE users
|
||||||
|
SET status = ${status}, updatedAt = ${utcdate}
|
||||||
|
WHERE name = ${name}
|
||||||
|
`;
|
||||||
|
|
||||||
|
await db.execute(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: true };
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating employee status by name:", error);
|
||||||
|
throw new Error("Failed to update status by name");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user