Files
internify-fe/src/Pages/internify/intern/components/ProjectTaskCard.tsx
T
Kemas M. Aryadary Rasyad 5689898f33 feat: enhance certificate management and project task features
- Updated CertificateForm to improve loading state UI with skeletons.
- Enhanced CertificateResult with better loading indicators and structure.
- Refactored ProjectForumTab to include a skeleton loader and improved error handling.
- Introduced ProjectTaskTab for managing project tasks with modals for creating and editing tasks.
- Improved ProjectsPage with a skeleton loader during project data fetching.
- Refined AddInternsToProjects, ArchiveProjectDialog, CompleteProjectDialog, CreateProjectDialog, CreateTaskDialog, and EditTaskDialog components to handle modal states more effectively.
- Updated EligibleInternTable to enhance loading states and formatting of dates.
- Modified StatusSubmissionTable to simplify status display.
- Improved certificate generation utility functions for better date formatting and layout management.
- Removed deprecated certificate assets and added a new template for certificates.
- Updated types for certificates and projects to include start and end dates.
2026-07-15 11:42:22 +07:00

67 lines
2.5 KiB
TypeScript

import { useNavigate } from "react-router-dom";
import type { InternTaskItem } from "../../../../types/project.types";
const formatDate = (dateStr: string) =>
new Date(dateStr).toLocaleDateString('id-ID', { day: 'numeric', month: 'short', year: 'numeric' });
const formatTime = (dateStr: string) =>
new Date(dateStr).toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit' });
type DisplayStatus = InternTaskItem["submission_status"] | "overdue";
const statusStyles: Record<DisplayStatus, string> = {
not_submitted: "bg-gray-50 text-gray-700 border-gray-200",
submitted: "bg-green-50 text-green-700 border-green-200",
overdue: "bg-red-50 text-red-700 border-red-200",
};
const statusLabels: Record<DisplayStatus, string> = {
not_submitted: "Pending",
submitted: "Submitted",
overdue: "Overdue",
};
export default function TaskCard({ task }: { task: InternTaskItem }) {
const navigate = useNavigate();
const displayStatus: DisplayStatus =
task.submission_status === "not_submitted" &&
new Date(task.deadline_at).getTime() < Date.now()
? "overdue"
: task.submission_status;
return (
<div
className="border border-card-outline rounded-xl px-6 py-4 mb-3 bg-box-primary flex items-start justify-between gap-3 cursor-pointer hover:bg-gray-50 transition-colors"
onClick={() => navigate(`/intern/projects/${task.project_slug}/${task.slug}?type=${task.submission_type}`)}
>
<div className="flex-1 min-w-0">
<div className="md:hidden mb-[8px]">
<span
className={`font-semibold text-xs px-2.5 py-1 rounded-md whitespace-nowrap border ${statusStyles[displayStatus]}`}>
{statusLabels[displayStatus]}
</span>
</div>
<div className="text-[11px] text-font mb-1">
Deadline : {formatDate(task.deadline_at)} at {formatTime(task.deadline_at)}
</div>
<div className="font-bold text-[15px] text-[#1a1a1a] mb-1">
{task.title}
</div>
<div className="text-[13px] text-font">
{task.description}
</div>
<div className="text-[13px] text-font mt-0.5">
Tipe Submission : {task.submission_type === 'file_upload' ? "File" : "Link"}
</div>
</div>
<div className="shrink-0 hidden md:flex items-center border border-card-outline">
<span
className={`font-semibold text-xs px-3.5 py-[5px] rounded-md whitespace-nowrap border ${statusStyles[displayStatus]}`}>
{statusLabels[task.submission_status]}
</span>
</div>
</div>
);
}