i have this next 13 page and endpoint and getting a 405 error
martnta
Posted on April 30, 2023
'use client'
import { useState } from 'react';
import { parse } from 'csv-parse';
import { Button } from '@/app/(app)/user/components/button';
interface FileInputEvent extends React.ChangeEvent<HTMLInputElement> {
target: HTMLInputElement & EventTarget;
}
interface LoanStatus {
studentId: string;
name: string;
hasActiveLoan: boolean;
email: string;
}
export default function Upload() {
const [data, setData] = useState<any[]>([]);
const [loanData, setLoanData] = useState<LoanStatus[]>([]);
function handleUpload(e: FileInputEvent) {
const files = e.target.files;
if (!files) return;
const file = files[0];
const reader = new FileReader();
reader.onload = () => {
const csvString = reader.result as string;
parse(csvString, {
columns: true,
skip_empty_lines: true,
}, (err, output) => {
if (err) {
console.error(err);
} else {
setData(output);
setLoanData(output as LoanStatus[]);
}
});
};
reader.readAsText(file);
}
const sendData = async () => {
const res = await fetch('/api/file2', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(loanData),
});
const jsonData = await res.json();
console.log(jsonData);
}
const handleLoanReminder = async () => {
const response = await fetch('/api/email', {
method: 'POST',
});
const jsonData = await response.json();
console.log(jsonData);
};
return (
<div className="max-w-md mx-auto p-4">
<h1 className="text-2xl font-bold mb-4">Upload a CSV file</h1>
<div className="flex flex-col mb-4">
<label htmlFor="csv" className="text-gray-700">Choose a CSV file</label>
<input type="file" accept=".csv" id="csv" className="mt-1 p-2 border text-black rounded" onChange={handleUpload} />
</div>
<button className="bg-yellow-600 text-white py-2 px-4 rounded" type="submit" onClick={sendData}>
Upload data
</button>
<table className="table-auto w-full mt-4">
<thead>
<tr>
<th className="text-left text-black px-4 py-2 border">Firstname</th>
<th className="text-left text-black px-4 py-2 border">Lastname</th>
<th className="text-left text-black px-4 py-2 border">Email</th>
<th className="text-left text-black px-4 py-2 border">National ID</th>
<th className="text-left text-black px-4 py-2 border">Organisation</th>
</tr>
</thead>
<tbody>
{data.map((row, index) => (
<tr key={index}>
<td className="text-left text-black px-4 py-2 border">{row.firstname}</td>
<td className="text-left text-black px-4 py-2 border">{row.lastname}</td>
<td className="border text-black px-4 py-2">{row.email}</td>
<td className="border text-black px-4 py-2">{row.nationalId}</td>
<td className="border text-black px-4 py-2">{row.company}</td>
</tr>
))}
</tbody>
</table>
<hr className="my-8" />
<h2 className="text-2xl text-black font-bold mb-6">Loan Status</h2>
{data ? (
<table className="table-auto w-full mb-8">
<thead>
<tr>
<th className="px-4 py-2 text-black text-left">Student ID</th>
<th className="px-4 py-2 text-left">Has Active Loan</th>
</tr>
</thead>
<tbody>
{data.map((status) => (
<tr key={status.studentId}>
<td className="border text-black px-4 py-2">{status.studentId}</td>
<td className="border text-black px-4 py-2">{status.hasActiveLoan ? 'Yes' : 'No'}</td>
</tr>
))}
</tbody>
</table>
) : (
<p className="font-medium text-xl text-gray-700 mb-8">No loan status to show.</p>
)}
<hr className="my-8" />
<Button onClick={handleLoanReminder}>Send Loan Reminder Emails</Button>
</div>
);
}
*en*
end point
import { NextApiRequest, NextApiResponse } from 'next';
import { PrismaClient } from '@prisma/client';
interface LoanStatus {
studentId: number;
name: string;
nationalId: string;
email: string;
hasActiveLoan: boolean;
message: string;
}
interface NextApiRequestWithFiles extends NextApiRequest {
body: {
data: {
nationalId: string;
}[];
};
}
export default async function handler(req: NextApiRequestWithFiles, res: NextApiResponse<LoanStatus[]>) {
if (req.method !== 'POST') {
res.setHeader('Allow', ['POST']);
res.status(405).end(`Method ${req.method} Not Allowed`);
return;
}
const { data } = req.body || {};
if (!data) {
res.status(400).json([{
studentId: 0,
name: '',
nationalId: '',
email: '',
hasActiveLoan: false,
message: 'No data provided',
}])
return;
}
const prisma = new PrismaClient();
const studentIds: number[] = [];
const loanStatus: LoanStatus[] = [];
for (const row of data) {
const student = await prisma.student.findFirst({
where: {
nationalId: row.nationalId,
},
});
if (student) {
studentIds.push(student.id);
}
}
const loans = await prisma.loan.findMany({
where: {
studentId: { in: studentIds },
status: 'active',
},
include: {
student: true,
},
});
for (const studentId of studentIds) {
const student = await prisma.student.findUnique({
where: { id: studentId },
});
if (student) {
const hasActiveLoan = loans.some(
(loan) => loan.studentId === studentId
);
loanStatus.push({
studentId,
name: student.username ?? '',
nationalId: student.nationalId ?? '',
email: student.email ?? '',
hasActiveLoan,
message: '',
});
}
}
await prisma.$disconnect();
res.status(200).json(loanStatus);
}
💖 💪 🙅 🚩
martnta
Posted on April 30, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
watercooler Why does a reboot make your PC run SO much faster than running all the cleaning tools you can possibly imagine?
November 30, 2024