export button

This commit is contained in:
Om Lanke
2025-09-23 00:10:14 +05:30
parent a9156127db
commit efe81705f5
2 changed files with 89 additions and 8 deletions

View File

@@ -0,0 +1,70 @@
'use client';
import { Button } from '@workspace/ui/components/button';
import { Download } from 'lucide-react';
type Applicant = {
applicationId: number;
status: string;
firstName: string | null;
lastName: string | null;
email: string | null;
studentId: number | null;
};
interface ExportButtonProps {
applicants: Applicant[];
jobId: number;
jobTitle: string;
}
export default function ExportButton({ applicants, jobId, jobTitle }: ExportButtonProps) {
const exportToCSV = () => {
if (applicants.length === 0) {
alert('No applications to export.');
return;
}
const headers = ['Application ID', 'Student Name', 'Email', 'Status'];
const csvData = applicants.map(applicant => [
applicant.applicationId.toString(),
`${applicant.firstName ?? ''} ${applicant.lastName ?? ''}`.trim() || 'Unknown',
applicant.email || '',
applicant.status
]);
const csvContent = [
headers.join(','),
...csvData.map(row => row.map(field => `"${field.replace(/"/g, '""')}"`).join(','))
].join('\n');
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
// Clean job title for filename
const cleanJobTitle = jobTitle.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase();
const filename = `${cleanJobTitle}-job-${jobId}-applications-${new Date().toISOString().split('T')[0]}.csv`;
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
};
return (
<Button
onClick={exportToCSV}
variant="outline"
size="sm"
className="flex items-center gap-2 text-gray-700 hover:text-gray-900 border-gray-300 hover:border-gray-400"
disabled={applicants.length === 0}
>
<Download className="w-4 h-4" />
Export to CSV
</Button>
);
}

View File

@@ -15,11 +15,13 @@ import {
ExternalLink, ExternalLink,
Users, Users,
FileText, FileText,
Clock Clock,
Download
} from 'lucide-react'; } from 'lucide-react';
import Link from 'next/link'; import Link from 'next/link';
import StatusSelect from './StatusSelect'; import StatusSelect from './StatusSelect';
import ApplicationsTable from './ApplicationsTable'; import ApplicationsTable from './ApplicationsTable';
import ExportButton from './ExportButton';
export const dynamic = 'force-dynamic'; export const dynamic = 'force-dynamic';
@@ -303,13 +305,22 @@ export default async function JobDetailPage({ params }: { params: Promise<{ jobI
<div className="mt-12"> <div className="mt-12">
<Card className="border border-gray-200 shadow-sm"> <Card className="border border-gray-200 shadow-sm">
<CardHeader> <CardHeader>
<CardTitle className="flex items-center gap-2"> <div className="flex items-center justify-between">
<Users className="w-5 h-5 text-gray-600" /> <div>
Student Applications ({applicants.length}) <CardTitle className="flex items-center gap-2">
</CardTitle> <Users className="w-5 h-5 text-gray-600" />
<CardDescription> Student Applications ({applicants.length})
View all students who have applied for this position </CardTitle>
</CardDescription> <CardDescription>
View all students who have applied for this position
</CardDescription>
</div>
<ExportButton
applicants={applicants}
jobId={jobId}
jobTitle={job.title}
/>
</div>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
{applicants.length === 0 ? ( {applicants.length === 0 ? (