Add legacy APIs so that I can migrate new app to techtracker.gibbyb.com and keep iOS app working
This commit is contained in:
		
							
								
								
									
										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]);
 | 
			
		||||
 | 
			
		||||
  const fetchEmployees = useCallback(async (): Promise<Employee[]> => {
 | 
			
		||||
    const res = await fetch('/api/get_employees', {
 | 
			
		||||
    const res = await fetch('/api/v2/get_employees', {
 | 
			
		||||
      method: 'GET',
 | 
			
		||||
      headers: {
 | 
			
		||||
        'Authorization': `Bearer ${process.env.API_KEY}`
 | 
			
		||||
@@ -86,7 +86,7 @@ export default function Table({ employees }: { employees: Employee[] }) {
 | 
			
		||||
 | 
			
		||||
  const handleSubmit = async () => {
 | 
			
		||||
    if (selectedIds.length > 0 && status.trim() !== '') {
 | 
			
		||||
      await fetch('/api/update_status', {
 | 
			
		||||
      await fetch('/api/v2/update_status', {
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        headers: {
 | 
			
		||||
          'Content-Type': 'application/json',
 | 
			
		||||
 
 | 
			
		||||
@@ -32,3 +32,114 @@ export const updateEmployeeStatus = async (employeeIds: string[], newStatus: str
 | 
			
		||||
    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");
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user