import { useState, useEffect } from "react"; import Layout from "@/components/Layout"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; import { Loader2, FileText, CheckCircle, Clock, XCircle, Eye, Trash2, } from "lucide-react"; import { getMyApplications, withdrawApplication } from "@/api/applications"; import { useNavigate } from "react-router-dom"; import { useAethexToast } from "@/hooks/use-aethex-toast"; import type { Application } from "@/api/applications"; export default function MyApplications() { const navigate = useNavigate(); const { toast } = useAethexToast(); const [applications, setApplications] = useState([]); const [isLoading, setIsLoading] = useState(true); const [selectedStatus, setSelectedStatus] = useState(); useEffect(() => { const fetchApplications = async () => { setIsLoading(true); try { const result = await getMyApplications({ status: selectedStatus, page: 1, limit: 50, }); setApplications(result.data); } catch (error) { console.error("Failed to fetch applications:", error); setApplications([]); } finally { setIsLoading(false); } }; fetchApplications(); }, [selectedStatus]); const handleWithdraw = async (applicationId: string) => { try { await withdrawApplication(applicationId); toast("Application withdrawn", "success"); setApplications(applications.filter((app) => app.id !== applicationId)); } catch (error) { toast( error instanceof Error ? error.message : "Failed to withdraw application", "error", ); } }; const getStatusColor = (status: string) => { switch (status) { case "submitted": return "bg-blue-500/10 text-blue-300"; case "reviewing": return "bg-yellow-500/10 text-yellow-300"; case "accepted": return "bg-green-500/10 text-green-300"; case "rejected": return "bg-red-500/10 text-red-300"; default: return "bg-gray-500/10 text-gray-300"; } }; const getStatusIcon = (status: string) => { switch (status) { case "submitted": return ; case "reviewing": return ; case "accepted": return ; case "rejected": return ; default: return null; } }; return (
{/* Background */}

My Applications

Track the status of all your job applications

{isLoading ? (
) : applications.length === 0 ? (

No applications yet

Start applying to opportunities to see them here

) : ( <> setSelectedStatus(value === "all" ? undefined : value) } className="mb-8" > All ({applications.length}) Submitted ( { applications.filter((app) => app.status === "submitted") .length } ) Reviewing ( { applications.filter((app) => app.status === "reviewing") .length } ) Accepted ( { applications.filter((app) => app.status === "accepted") .length } ) Rejected ( { applications.filter((app) => app.status === "rejected") .length } ) {applications.map((app) => ( navigate(`/opportunities/${app.opportunity_id}`) } /> ))} {["submitted", "reviewing", "accepted", "rejected"].map( (status) => ( {applications .filter((app) => app.status === status) .map((app) => ( navigate(`/opportunities/${app.opportunity_id}`) } /> ))} ), )} )}
); } interface ApplicationCardProps { application: Application; statusColor: string; statusIcon: React.ReactNode; onWithdraw: (id: string) => void; onViewOpportunity: () => void; } function ApplicationCard({ application, statusColor, statusIcon, onWithdraw, onViewOpportunity, }: ApplicationCardProps) { const opportunity = application.aethex_opportunities; if (!opportunity) return null; const poster = opportunity.aethex_creators; return (

{opportunity.title}

{statusIcon} {application.status.charAt(0).toUpperCase() + application.status.slice(1)}
{poster.username.charAt(0).toUpperCase()}

Posted by

@{poster.username}

Applied on {new Date(application.applied_at).toLocaleDateString()}

{application.response_message && (

{application.response_message}

)}
{application.status === "submitted" && ( )}
); }