feat: update project task card to use new task type and improve navigation
fix: update project card to reflect actual tasks done from project data feat: enhance task form components to accept project ID for submissions refactor: clean up certificate detail page by removing unused elements chore: streamline certificate generation page by removing unnecessary navigation refactor: update certificate list page to use dynamic project data feat: improve interns management page with API integration and better state handling feat: add modal for assigning interns to projects with project selection feat: create a new component for displaying project cards in certificate list fix: correct import paths in create project dialog component refactor: enhance project hooks to include task filtering and refetch capabilities fix: update mock certificate data to reflect correct status feat: extend certificate types to include new fields for better tracking feat: add task_done field to project types for improved task management
This commit is contained in:
@@ -1,38 +1,69 @@
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { History } from "lucide-react";
|
||||
import { type CertificateHistory, history as certificateHistory } from "../../../../lib/mockSertificates";
|
||||
import { History, Loader2, AlertCircle } from "lucide-react";
|
||||
import type { Certificate } from "../../../../types/certificate.types";
|
||||
import certificateImg from "../../../../assets/certificate.png";
|
||||
import { useMyCertificates } from "../../../../hooks/useSertificates";
|
||||
|
||||
export default function SertificateHistory() {
|
||||
const navigate = useNavigate();
|
||||
const { certificates, loading, error } = useMyCertificates();
|
||||
const displayed = certificates.slice(0, 2);
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-2xl border border-gray-200 shadow-sm p-5">
|
||||
<div className="bg-box-primary rounded-2xl border border-box-border shadow-sm p-5">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<History className="w-5 h-5 text-red-700" />
|
||||
<h3 className="font-semibold text-gray-800 text-lg">Certificate History</h3>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{certificateHistory.slice(0, 2).map((item: CertificateHistory) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="flex flex-col gap-3 p-3 bg-white border border-gray-200 shadow-sm rounded-xl hover:bg-gray-50 transition-colors cursor-pointer"
|
||||
>
|
||||
<div className="w-full flex justify-center">
|
||||
<img
|
||||
src={certificateImg}
|
||||
alt="Certificate"
|
||||
className="rounded-xl h-[150px] w-[150px] w-full object-cover"
|
||||
/>
|
||||
{loading && (
|
||||
<div className="flex items-center justify-center py-8 text-gray-400 gap-2">
|
||||
<Loader2 className="w-5 h-5 animate-spin" />
|
||||
<span className="text-sm">Loading certificates...</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && !loading && (
|
||||
<div className="flex items-center gap-2 py-6 text-red-500">
|
||||
<AlertCircle className="w-4 h-4" />
|
||||
<span className="text-sm">{error}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!loading && !error && displayed.length === 0 && (
|
||||
<p className="text-sm text-gray-400 py-6 text-center">No certificates yet.</p>
|
||||
)}
|
||||
|
||||
{!loading && !error && displayed.length > 0 && (
|
||||
<div className="space-y-3">
|
||||
{displayed.map((item: Certificate) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="flex flex-col gap-3 p-3 bg-white border border-gray-200 shadow-sm rounded-xl hover:bg-gray-50 transition-colors cursor-pointer"
|
||||
>
|
||||
<div className="w-full flex justify-center">
|
||||
<img
|
||||
src={certificateImg}
|
||||
alt="Certificate"
|
||||
className="rounded-xl h-[150px] w-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<p className="text-xs text-gray-400">
|
||||
{new Date(item.issued_at).toLocaleDateString("id-ID", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
})}
|
||||
</p>
|
||||
<p className="text-sm font-semibold text-gray-800 leading-tight">
|
||||
{item.project.project_name}
|
||||
</p>
|
||||
<p className="text-sm text-gray-500">No: {item.certificate_no}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<p className="text-xs text-gray-400">{item.month}</p>
|
||||
<p className="text-sm font-semibold text-gray-800 leading-tight">{item.title}</p>
|
||||
<p className="text-sm text-gray-500">Grade: {item.grade}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="w-full my-3 flex justify-end">
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user