diff --git a/package-lock.json b/package-lock.json index fd6c0a9..c8e37cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "react-dom": "^18.2.0", "react-froala-wysiwyg": "^4.5.2", "react-google-recaptcha": "^3.1.0", + "react-hot-toast": "^2.6.0", "react-icons": "^5.5.0", "react-router-dom": "^7.6.0", "recharts": "^3.4.1", @@ -2808,7 +2809,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true, "license": "MIT" }, "node_modules/d3-array": { @@ -3537,6 +3537,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/goober": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.19.tgz", + "integrity": "sha512-U7veizMqxyKlM58+Z5j2ngJBH/r9siDmxpvNxSw0PylF6WQvrASJEZrxh1hidRBJc2jqoBVSyOban5u8m+6Rxg==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -4702,6 +4711,23 @@ "react": ">=16.4.1" } }, + "node_modules/react-hot-toast": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz", + "integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.3", + "goober": "^2.1.16" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-icons": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", diff --git a/package.json b/package.json index 64df5b4..2e3fbd4 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "react-dom": "^18.2.0", "react-froala-wysiwyg": "^4.5.2", "react-google-recaptcha": "^3.1.0", + "react-hot-toast": "^2.6.0", "react-icons": "^5.5.0", "react-router-dom": "^7.6.0", "recharts": "^3.4.1", diff --git a/src/App.tsx b/src/App.tsx index df11426..731db6a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -44,6 +44,7 @@ import NotificationList from "./Pages/internify/NotificationList"; import SettingsContent from "./Pages/internify/SettingsPage"; import TaskSubmission from "./Pages/internify/intern/TaskSubmission"; import SertificateList from "./Pages/internify/intern/SertificateList"; +import MentorProjectsDetailPage from "./Pages/internify/mentor/MentorProjectDetailPage"; function App() { return ( @@ -102,6 +103,7 @@ function App() { } /> } /> } /> + } /> } /> } /> } /> diff --git a/src/Pages/internify/Breadcumbs.tsx b/src/Pages/internify/Breadcumbs.tsx index e0320e2..d2a28e6 100644 --- a/src/Pages/internify/Breadcumbs.tsx +++ b/src/Pages/internify/Breadcumbs.tsx @@ -34,6 +34,7 @@ const breadcrumbRoutes = [ { path: '/mentor', breadcrumb: 'Home' }, { path: '/mentor/projects', breadcrumb: 'List Projects' }, { path: '/mentor/projects/:slug', breadcrumb: ProjectNameBreadcrumb }, + { path: '/mentor/projects/:slug/:taskSlug', breadcrumb: TaskNameBreadcrumb }, { path: '/mentor/certificates', breadcrumb: 'Approve Certificates' }, { path: '/mentor/intern', breadcrumb: 'List Intern' }, { path: '/mentor/faq', breadcrumb: 'FAQ' }, diff --git a/src/Pages/internify/intern/ForumTab.tsx b/src/Pages/internify/intern/ForumTab.tsx index 83ad3aa..4ee64c1 100644 --- a/src/Pages/internify/intern/ForumTab.tsx +++ b/src/Pages/internify/intern/ForumTab.tsx @@ -1,4 +1,4 @@ -import type { Project } from '../../../lib/mockData'; +import type { Project } from '../../../lib/mockProjects'; import ProjectTimeline from './components/ProjectTimeline'; import TaskCard from './components/ProjectTaskCard'; import HeroProject from './components/Hero-project'; diff --git a/src/Pages/internify/intern/ProjectDetailPage.tsx b/src/Pages/internify/intern/ProjectDetailPage.tsx index a2c6187..9d21cc0 100644 --- a/src/Pages/internify/intern/ProjectDetailPage.tsx +++ b/src/Pages/internify/intern/ProjectDetailPage.tsx @@ -27,7 +27,7 @@ export default function ProjectDetailPage() { }`; return ( -
+
{/* Tabs */}
diff --git a/src/Pages/internify/intern/components/HomeCalendar.tsx b/src/Pages/internify/intern/components/HomeCalendar.tsx index 7f9ab9b..f629998 100644 --- a/src/Pages/internify/intern/components/HomeCalendar.tsx +++ b/src/Pages/internify/intern/components/HomeCalendar.tsx @@ -1,16 +1,7 @@ import { useState, useEffect } from 'react' import { ChevronLeft, ChevronRight } from 'lucide-react' +import { DEADLINES } from '../../../../lib/mockDeadline' -interface Deadline { - date: number - month: number - year: number - label: string -} - -const DEADLINES: Deadline[] = [ - { date: 30, month: 6, year: 2026, label: 'Tenggat Proyek Internify Internify - 4 May' }, -] const DAY_LABELS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] const MONTH_NAMES = [ @@ -19,7 +10,7 @@ const MONTH_NAMES = [ ] function getDaysInMonth(year: number, month: number) { - return new Date(year, month+1, 0).getDate() + return new Date(year, month + 1, 0).getDate() } function getFirstDayOfMonth(year: number, month: number) { @@ -27,7 +18,7 @@ function getFirstDayOfMonth(year: number, month: number) { } const HomeCalendar = () => { -const [today, setToday] = useState(new Date()) + const [today, setToday] = useState(new Date()) useEffect(() => { const interval = setInterval(() => { @@ -67,11 +58,18 @@ const [today, setToday] = useState(new Date()) currentYear === today.getFullYear() const hasDeadline = (day: number) => - DEADLINES.some(d => d.date === day && d.month - 1 === currentMonth && d.year === currentYear) + DEADLINES.some(d => + d.date.getDate() === day && + d.date.getMonth() === currentMonth && + d.date.getFullYear() === currentYear + ) - const upcomingDeadlines = DEADLINES.filter( - d => d.month === currentMonth && d.year === currentYear - ) + const upcomingDeadlines = DEADLINES.filter(d => { + return ( + d.date.getMonth() === currentMonth && + d.date.getFullYear() === currentYear + ); + }).sort((a, b) => a.date.getTime() - b.date.getTime()); // Previous month trailing days const prevMonthDays = getDaysInMonth(currentYear, currentMonth - 1 < 0 ? 11 : currentMonth - 1) @@ -135,16 +133,16 @@ const [today, setToday] = useState(new Date()) {/* Current month days */} {currentDays.map(day => ( -
+
{isToday(day) ? ( {day} ) : ( {day} diff --git a/src/Pages/internify/intern/components/ProjectTimeline.tsx b/src/Pages/internify/intern/components/ProjectTimeline.tsx index e51a9ce..a22313a 100644 --- a/src/Pages/internify/intern/components/ProjectTimeline.tsx +++ b/src/Pages/internify/intern/components/ProjectTimeline.tsx @@ -1,4 +1,4 @@ -import type { Task } from "../../../../lib/mockData"; +import type { Task } from "../../../../lib/mockProjects"; import { ArrowDownNarrowWide } from "lucide-react"; const formatDate = (date: Date) => @@ -11,7 +11,7 @@ export default function ProjectTimeline({ tasks }: { tasks: Task[] }) { return (
- + Timeline @@ -29,7 +29,7 @@ export default function ProjectTimeline({ tasks }: { tasks: Task[] }) {
  • {/* Dot */}
    {mockProjects.map(project => ( - + ))}
    diff --git a/src/Pages/internify/mentor/MentorProjectDetailPage.tsx b/src/Pages/internify/mentor/MentorProjectDetailPage.tsx new file mode 100644 index 0000000..422cebe --- /dev/null +++ b/src/Pages/internify/mentor/MentorProjectDetailPage.tsx @@ -0,0 +1,141 @@ +import { useParams } from "react-router-dom"; +import { mockProjects } from "../../../lib/mockProjects"; +import { Calendar, Edit, SlidersHorizontal, Search } from "lucide-react"; + +const toSlug = (name: string) => name.toLowerCase().replace(/\s+/g, '-'); + +// Helper untuk mendapatkan inisial nama avatar +const getInitials = (name: string) => { + return name.split(' ').map(n => n[0]).join('').substring(0, 2).toUpperCase(); +}; + +export default function MentorProjectsDetailPage() { + const { slug, taskSlug } = useParams<{ slug: string; taskSlug: string }>(); + + const targetedProject = mockProjects.find((p) => toSlug(p.name) === slug); + if (!targetedProject) { + return
    Project tidak ditemukan.
    ; + } + + const targetedTask = targetedProject.tasks.find((t) => toSlug(t.title) === taskSlug); + if (!targetedTask) { + return
    Tugas tidak ditemukan.
    ; + } + + return ( +
    + + {/* Header Utama */} +
    +

    {targetedTask.title}

    + +
    + + {/* Kotak Informasi Detail & Deadline */} +
    +
    +

    Description

    +

    + {targetedTask.description} +

    +
    +
    +

    Deadline

    +
    +
    + +
    +
    +
    {targetedTask.deadline.label}
    +
    at {targetedTask.deadline.time}
    +
    +
    +
    +
    + + {/* Panel Tabel Intern Submissions */} +
    + {/* Header Tabel Kontrol */} +
    +
    +

    Intern Submissions

    + + {targetedTask.submissions?.length || 0} total + +
    +
    + + +
    +
    + + {/* Isi Tabel */} +
    + + + + + + + + + + + {targetedTask.submissions?.map((sub, idx) => { + // Cari relasi profil lengkap intern lewat email + const internProfile = targetedProject.interns.find(i => i.email === sub.internEmail); + if (!internProfile) return null; + + return ( + + {/* Kolom Nama & Profil */} + + + {/* Kolom Tanggal Kumpul */} + + + {/* Kolom Badge Status */} + + + {/* Kolom Tombol Aksi */} + + + ); + })} + +
    Intern NameSubmitted DateStatusActions
    +
    + {getInitials(internProfile.name)} +
    + {internProfile.name} +
    + {sub.submittedAt || "-"} + + {sub.status === "Done" && ( + + Done + + )} + {sub.status === "Pending" && ( + + Pending + + )} + {sub.status === "Overdue" && ( + + Overdue + + )} + + +
    +
    +
    +
    + ); +} \ No newline at end of file diff --git a/src/Pages/internify/mentor/ProjectForumTab.tsx b/src/Pages/internify/mentor/ProjectForumTab.tsx index 4806cf1..ba73be3 100644 --- a/src/Pages/internify/mentor/ProjectForumTab.tsx +++ b/src/Pages/internify/mentor/ProjectForumTab.tsx @@ -1,4 +1,4 @@ -import type { Project } from '../../../lib/mockData'; +import type { Project } from '../../../lib/mockProjects'; import ProjectTimeline from '../intern/components/ProjectTimeline'; import HeroProject from '../intern/components/Hero-project'; import MentorTaskCard from './components/MentorTaskCard'; @@ -17,7 +17,10 @@ export default function MentorForumTab({ project }: { project: Project }) {
    {project.tasks.map((task, idx) => ( - + ))}
    diff --git a/src/Pages/internify/mentor/ProjectsInternTab.tsx b/src/Pages/internify/mentor/ProjectsInternTab.tsx index 59ee25f..0c645d5 100644 --- a/src/Pages/internify/mentor/ProjectsInternTab.tsx +++ b/src/Pages/internify/mentor/ProjectsInternTab.tsx @@ -45,7 +45,7 @@ export default function InternsTab({ project }: { project: Project }) { >
    - {intern.email} + {intern.name}
    diff --git a/src/Pages/internify/mentor/ProjectsPage.tsx b/src/Pages/internify/mentor/ProjectsPage.tsx index 2a7b823..aeef2f9 100644 --- a/src/Pages/internify/mentor/ProjectsPage.tsx +++ b/src/Pages/internify/mentor/ProjectsPage.tsx @@ -1,11 +1,10 @@ import { useState } from 'react'; -import { useNavigate, useParams } from 'react-router-dom'; +import { useParams } from 'react-router-dom'; import { mockProjects } from '../../../lib/mockProjects'; import MentorForumTab from './ProjectForumTab'; import InternsTab from './ProjectsInternTab'; import TaskTab from './TaskTab'; -// ─── ProjectDetailPage ───────────────────────────────────────────────────────── const toSlug = (name: string) => name.toLowerCase().replace(/\s+/g, '-'); export default function ProjectDetailPage() { @@ -53,7 +52,7 @@ export default function ProjectDetailPage() { case 'participants': return ; case 'Task': - return ; // Tambahkan komponen TaskTab di sini + return ; default: return null; } diff --git a/src/Pages/internify/mentor/components/HomeMentorProject.tsx b/src/Pages/internify/mentor/components/HomeMentorProject.tsx index 6525d9d..056a4d6 100644 --- a/src/Pages/internify/mentor/components/HomeMentorProject.tsx +++ b/src/Pages/internify/mentor/components/HomeMentorProject.tsx @@ -1,17 +1,28 @@ import { useNavigate } from 'react-router-dom' import { mockProjects } from '../../../../lib/mockData' +import { useState } from 'react'; import { Plus } from 'lucide-react'; +import CreateProjectModal from './CreateProjectDialog'; const HomeMentorProject = () => { const navigate = useNavigate(); + const [isModalOpen, setIsModalOpen] = useState(false); + const openDialog = () => { + setIsModalOpen(true); + }; + const closeDialog = () => { + setIsModalOpen(false); + }; return (

    Projects

    -
    @@ -20,7 +31,7 @@ const HomeMentorProject = () => { return (
    navigate(`/intern/projects/${project.id}`)} + onClick={() => navigate(`/intern/projects/${project.name}`)} className="flex items-center gap-4 border border-gray-200 rounded-lg px-4 py-3 hover:bg-gray-50 cursor-pointer transition-colors duration-150" >
    @@ -32,6 +43,12 @@ const HomeMentorProject = () => { ) })}
    + {isModalOpen && ( + + )}
    ) } diff --git a/src/Pages/internify/mentor/components/MentorProjectCard.tsx b/src/Pages/internify/mentor/components/MentorProjectCard.tsx index 3707ff3..e579cb0 100644 --- a/src/Pages/internify/mentor/components/MentorProjectCard.tsx +++ b/src/Pages/internify/mentor/components/MentorProjectCard.tsx @@ -1,11 +1,12 @@ import { Trash2, UsersRound } from 'lucide-react' -import type { Intern } from '../../../../lib/mockProjects' +import type { Intern, Task } from '../../../../lib/mockProjects' import { useNavigate } from 'react-router-dom' interface ProjectCardProps { id: number | string name: string interns: Intern[] + tasks: Task[] thumbnailUrl?: string } diff --git a/src/Pages/internify/mentor/components/MentorTaskCard.tsx b/src/Pages/internify/mentor/components/MentorTaskCard.tsx index 060ae2d..514da44 100644 --- a/src/Pages/internify/mentor/components/MentorTaskCard.tsx +++ b/src/Pages/internify/mentor/components/MentorTaskCard.tsx @@ -1,34 +1,46 @@ -import type { Task } from "../../../../lib/mockData"; +import type { Task } from "../../../../lib/mockProjects"; +import { useNavigate } from "react-router-dom"; const formatDate = (date: Date) => new Date(date).toLocaleDateString('id-ID', { day: 'numeric', month: 'short', year: 'numeric' }); -export default function MentorTaskCard({ task }: { task: Task }) { +const toSlug = (name: string) => name.toLowerCase().replace(/\s+/g, '-'); + +interface MentorTaskCardProps { + task: Task; + projectName: string; +} + +export default function MentorTaskCard({ task, projectName }: MentorTaskCardProps) { + const navigate = useNavigate(); + + const handleCardClick = () => { + // Pastikan jika projectName belum ter-render, proses navigasi tidak bikin crash + if (!projectName || !task?.title) return; + + const projectSlug = toSlug(projectName); + const taskSlug = toSlug(task.title); + + // Rute mutlak menuju target kamu: /mentor/projects/:slug/:taskSlug + navigate(`/mentor/projects/${projectSlug}/${taskSlug}`); + }; + return ( -
    +
    -
    - Deadline : {formatDate(task.deadline.date)} at {task.deadline.time} +
    + Deadline : {task.deadline ? `${formatDate(task.deadline.date)} at ${task.deadline.time}` : '-'}
    -
    +
    {task.title}
    -
    +
    {task.description}
    - -
    - - {task.submittedCount}/{task.totalInterns} - -
    ); } \ No newline at end of file diff --git a/src/lib/mockDeadline.ts b/src/lib/mockDeadline.ts index 0a74ae2..dd97574 100644 --- a/src/lib/mockDeadline.ts +++ b/src/lib/mockDeadline.ts @@ -6,15 +6,13 @@ export interface Deadline { export const DEADLINES: Deadline[] = [ { - date: new Date(2025, 4, 4), - label: "Laporan Progress 1 Internify – 4 Juni", + date: new Date(2026, 5, 29), + label: "Laporan Progress 1 Internify", time: "23:59 PM", }, { - date: new Date(2026, 5, 5), - label: "Laporan Progress 2 Internify - 5 May", + date: new Date(2026, 5, 30), + label: "Laporan Progress 2 Internify", time: "23:59 PM", }, -]; - -export const deadlineDates: Date[] = DEADLINES.map((d) => d.date); \ No newline at end of file +]; \ No newline at end of file diff --git a/src/lib/mockProjects.ts b/src/lib/mockProjects.ts index 37c2d8c..5356c81 100644 --- a/src/lib/mockProjects.ts +++ b/src/lib/mockProjects.ts @@ -1,14 +1,21 @@ import type { Deadline } from "./mockDeadline"; +export interface Submission { + internEmail: string; + submittedAt?: string; + status: 'Done' | 'Pending' | 'Overdue'; +} + export interface Task { id: number; title: string; description: string; deadline: Deadline; type: 'file' | 'link'; - isSubmitted: boolean; - submittedCount: number; - totalInterns: number; + submissions: Submission[]; + isSubmitted: boolean; // Kembalikan untuk komponen lain + submittedCount: number; // Kembalikan untuk komponen lain + totalInterns: number; // Kembalikan untuk komponen lain } export interface Intern { @@ -38,54 +45,50 @@ export const mockProjects: Project[] = [ description: "Internify merupakan website Human Capital (HUMC) yang dirancang sebagai platform pendaftaran dan pengelolaan program magang secara digital. Sistem ini dibuat untuk membantu proses rekrutmen peserta magang mulai dari pendaftaran, seleksi, hingga monitoring aktivitas peserta selama program berlangsung.\n\nFokus utama dari pengembangan Internify adalah pembuatan Learning Management System (LMS) yang digunakan untuk mendukung kegiatan pembelajaran dan pengelolaan peserta magang. LMS pada Internify menyediakan fitur seperti akses materi pembelajaran, pengumpulan tugas, monitoring progress peserta, absensi, sertifikat, hingga komunikasi antara mentor dan peserta magang.", tasks: [ - { - id: 1, - title: "Laporan tugas", - description: "Berisi design ulux, dan user flow dari aplikasi internify", - type: 'link', - deadline: { date: new Date(2026, 4, 1), label: "Laporan tugas – 1 Mei", time: "23:59 PM" }, - submittedCount: 6, - totalInterns: 6, - isSubmitted: false, - }, { id: 2, title: "Laporan tugas 1", - description: "Berisi design ulux, dan user flow dari aplikasi internify", + description: "Berisi design uiux, dan user flow dari aplikasi internify.", type: 'file', - deadline: { date: new Date(2026, 4, 14), label: "Laporan tugas 1 – 14 Mei", time: "23:59 PM" }, + deadline: { date: new Date(2026, 4, 14), label: "May 14, 2026", time: "23:59 PM" }, + isSubmitted: false, submittedCount: 2, totalInterns: 6, - isSubmitted: false, + submissions: [ + { internEmail: "jonathankristina@gmail.com", submittedAt: "May 12, 2026", status: "Done" }, + { internEmail: "anisarahmawati@gmail.com", submittedAt: "May 13, 2026", status: "Done" }, + { internEmail: "budisantoso@gmail.com", submittedAt: "-", status: "Pending" }, + { internEmail: "cindypermata@gmail.com", submittedAt: "-", status: "Pending" }, + { internEmail: "dewaaditya@gmail.com", submittedAt: "-", status: "Pending" }, + { internEmail: "ekapratiwi@gmail.com", submittedAt: "-", status: "Pending" }, + ] }, { id: 3, title: "Laporan tugas 2", - description: "Berisi design ulux, dan user flow dari aplikasi internify", + description: "Berisi design uiux, dan user flow dari aplikasi internify. Pastikan semua link Figma dapat diakses oleh mentor dan mencakup setidaknya 15 screen utama beserta prototype interaktifnya.", type: 'link', - deadline: { date: new Date(2026, 4, 28), label: "Laporan tugas 2 – 28 Mei", time: "23:59 PM" }, + deadline: { date: new Date(2026, 4, 28), label: "May 28, 2026", time: "23:59 PM" }, + isSubmitted: false, submittedCount: 3, totalInterns: 6, - isSubmitted: false, - }, - { - id: 4, - title: "Laporan tugas 3", - description: "Berisi wireframe halaman dashboard aplikasi internify", - type: 'file', - deadline: { date: new Date(2026, 5, 5), label: "Laporan tugas 3 – 5 Jun", time: "23:59 PM" }, - submittedCount: 0, - totalInterns: 6, - isSubmitted: false, + submissions: [ + { internEmail: "jonathankristina@gmail.com", submittedAt: "May 25, 2026", status: "Done" }, + { internEmail: "anisarahmawati@gmail.com", submittedAt: "May 26, 2026", status: "Pending" }, + { internEmail: "budisantoso@gmail.com", submittedAt: "May 26, 2026", status: "Done" }, + { internEmail: "cindypermata@gmail.com", submittedAt: "May 27, 2026", status: "Pending" }, + { internEmail: "dewaaditya@gmail.com", submittedAt: "-", status: "Overdue" }, + { internEmail: "ekapratiwi@gmail.com", submittedAt: "May 28, 2026", status: "Done" }, + ] }, ], interns: [ - { name: "Jonathan Kristina", role: "Backend", email: "jonathankristina@gmail.com" }, - { name: "Anisa Rahmawati", role: "Backend", email: "jonathankristina@gmail.com" }, - { name: "Budi Santoso", role: "Frontend", email: "jonathankristina@gmail.com" }, - { name: "Cindy Permata", role: "Frontend", email: "jonathankristina@gmail.com" }, - { name: "Dewa Aditya", role: "UI/UX", email: "jonathankristina@gmail.com" }, - { name: "Eka Pratiwi", role: "UI/UX", email: "jonathankristina@gmail.com" }, + { name: "Alex Rivera", role: "Backend", email: "jonathankristina@gmail.com" }, + { name: "Sarah Jenkins", role: "Backend", email: "anisarahmawati@gmail.com" }, + { name: "Marcus Lee", role: "Frontend", email: "budisantoso@gmail.com" }, + { name: "Tanya Hudson", role: "Frontend", email: "cindypermata@gmail.com" }, + { name: "Ben King", role: "UI/UX", email: "dewaaditya@gmail.com" }, + { name: "Eka Pratiwi", role: "UI/UX", email: "ekapratiwi@gmail.com" }, ], mentor: "jonathankristina@gmail.com", progress: 12, @@ -95,58 +98,24 @@ export const mockProjects: Project[] = [ { id: 2, name: "Rekrutmen Digital Platform", - description: - "Platform digital yang memudahkan proses rekrutmen karyawan baru secara end-to-end. Mulai dari posting lowongan, screening CV otomatis, penjadwalan wawancara, hingga onboarding karyawan baru.\n\nSistem ini mengintegrasikan berbagai modul HR seperti manajemen data kandidat, penilaian kompetensi berbasis AI, dan dashboard analytics untuk tim HR dalam mengambil keputusan rekrutmen yang lebih efektif dan efisien.", + description: "Platform digital yang memudahkan proses rekrutmen karyawan baru secara end-to-end.", tasks: [ { id: 1, title: "Analisis Kebutuhan Sistem", - description: "Dokumentasi kebutuhan fungsional dan non-fungsional platform rekrutmen", + description: "Dokumentasi kebutuhan platform rekrutmen", type: 'file', - deadline: { date: new Date(2026, 4, 5), label: "Analisis Kebutuhan – 5 Mei", time: "23:59 PM" }, + deadline: { date: new Date(2026, 4, 5), label: "May 5, 2026", time: "23:59 PM" }, + isSubmitted: false, submittedCount: 6, totalInterns: 6, - isSubmitted: false, - }, - { - id: 2, - title: "Desain Database Schema", - description: "Rancangan struktur database untuk kandidat, lowongan, dan proses seleksi", - type: 'link', - deadline: { date: new Date(2026, 4, 10), label: "Desain Database – 10 Mei", time: "23:59 PM" }, - submittedCount: 6, - totalInterns: 6, - isSubmitted: false, - }, - { - id: 3, - title: "Implementasi Auth Module", - description: "Pengembangan sistem autentikasi dan otorisasi multi-role", - type: 'file', - deadline: { date: new Date(2026, 4, 18), label: "Auth Module – 18 Mei", time: "23:59 PM" }, - submittedCount: 3, - totalInterns: 6, - isSubmitted: false, - }, - { - id: 4, - title: "Modul Posting Lowongan", - description: "Fitur buat, edit, dan publish lowongan pekerjaan", - type: 'link', - deadline: { date: new Date(2026, 4, 25), label: "Posting Lowongan – 25 Mei", time: "23:59 PM" }, - submittedCount: 0, - totalInterns: 6, - isSubmitted: false, - }, + submissions: [ + { internEmail: "fajarnugroho@gmail.com", submittedAt: "May 4, 2026", status: "Done" }, + ] + } ], interns: [ { name: "Fajar Nugroho", role: "Backend", email: "fajarnugroho@gmail.com" }, - { name: "Gita Melinda", role: "Backend", email: "gitamelinda@gmail.com" }, - { name: "Hendra Wijaya", role: "Frontend", email: "hendrawijaya@gmail.com" }, - { name: "Indira Sari", role: "Frontend", email: "indirasari@gmail.com" }, - { name: "Joko Purnomo", role: "UI/UX", email: "jokopurnomo@gmail.com" }, - { name: "Kartika Dewi", role: "QA", email: "kartikadewi@gmail.com" }, - { name: "Lukman Hakim", role: "QA", email: "lukmanhakim@gmail.com" }, ], mentor: "seniormHR@company.com", progress: 37, @@ -156,57 +125,24 @@ export const mockProjects: Project[] = [ { id: 3, name: "E-Commerce Analytics Dashboard", - description: - "Dashboard analitik komprehensif untuk platform e-commerce yang menyajikan insight real-time tentang performa penjualan, perilaku pelanggan, dan efektivitas kampanye marketing.\n\nProyek ini mencakup pengembangan pipeline data dari berbagai sumber transaksi, visualisasi interaktif menggunakan chart library modern, serta fitur export laporan dalam berbagai format untuk kebutuhan manajemen bisnis.", + description: "Dashboard analitik komprehensif untuk platform e-commerce.", tasks: [ { id: 1, title: "Setup Pipeline Data", description: "Konfigurasi ETL pipeline dari database transaksi ke data warehouse", type: 'link', - deadline: { date: new Date(2026, 4, 3), label: "Setup Pipeline – 3 Mei", time: "23:59 PM" }, + deadline: { date: new Date(2026, 4, 3), label: "May 3, 2026", time: "23:59 PM" }, + isSubmitted: false, submittedCount: 6, totalInterns: 6, - isSubmitted: false, - }, - { - id: 2, - title: "Desain Komponen Chart", - description: "Pembuatan reusable chart component untuk berbagai tipe visualisasi data", - type: 'file', - deadline: { date: new Date(2026, 4, 12), label: "Komponen Chart – 12 Mei", time: "23:59 PM" }, - submittedCount: 6, - totalInterns: 6, - isSubmitted: false, - }, - { - id: 3, - title: "Dashboard Overview Page", - description: "Halaman utama dengan ringkasan KPI dan metric utama bisnis", - type: 'link', - deadline: { date: new Date(2026, 4, 20), label: "Overview Page – 20 Mei", time: "23:59 PM" }, - submittedCount: 0, - totalInterns: 6, - isSubmitted: false, - }, - { - id: 4, - title: "Laporan Penjualan", - description: "Modul analitik penjualan dengan filter periode dan kategori produk", - type: 'file', - deadline: { date: new Date(2026, 4, 28), label: "Laporan Penjualan – 28 Mei", time: "23:59 PM" }, - submittedCount: 0, - totalInterns: 6, - isSubmitted: false, - }, + submissions: [ + { internEmail: "mayaanggraeni@gmail.com", submittedAt: "May 2, 2026", status: "Done" }, + ] + } ], interns: [ { name: "Maya Anggraeni", role: "Backend", email: "mayaanggraeni@gmail.com" }, - { name: "Nando Pratama", role: "Backend", email: "nandopratama@gmail.com" }, - { name: "Olivia Susanto", role: "Frontend", email: "oliviasusanto@gmail.com" }, - { name: "Pandu Kusuma", role: "Frontend", email: "pandukukusuma@gmail.com" }, - { name: "Qori Ramadhan", role: "Data Analyst", email: "qoriramadhan@gmail.com" }, - { name: "Rini Handayani", role: "UI/UX", email: "rinihandayani@gmail.com" }, ], mentor: "leadanalyst@company.com", progress: 50,