feat: add react-hot-toast for notifications, enhance project detail page, and update task handling

- Added `react-hot-toast` dependency for improved notification handling.
- Introduced `MentorProjectsDetailPage` for detailed project and task views.
- Updated routing to include task-specific paths.
- Enhanced breadcrumb navigation to reflect new project structure.
- Refactored task handling in `MentorTaskCard` and `ProjectTimeline` components.
- Updated mock data to include detailed task submissions and deadlines.
- Improved UI elements for better user experience in project management.
This commit is contained in:
Kemas M. Aryadary Rasyad
2026-06-16 17:54:00 +07:00
parent f9bb21a961
commit ff68115fca
19 changed files with 317 additions and 182 deletions
+1 -1
View File
@@ -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';
@@ -27,7 +27,7 @@ export default function ProjectDetailPage() {
}`;
return (
<div className="">
<div>
<div>
{/* Tabs */}
<div className="flex mb-4">
@@ -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 => (
<div key={day} className="flex justify-center items-center py-1 px-4">
<div key={day} className="flex justify-center items-center py-0.5">
{isToday(day) ? (
<span className="w-8 h-7 flex items-center justify-center border-b-2 border-red-800 text-xs font-semibold">
{day}
</span>
) : (
<span
className={`w-full h-7 flex items-center justify-center text-xs rounded
className={`w-full h-7 flex items-center justify-center text-xs
${isBold(day) ? 'font-bold text-gray-800' : 'text-gray-700'}
${hasDeadline(day) ? 'bg-red-700 text-white' : ''}
${hasDeadline(day) ? 'bg-red-800 text-white' : ''}
transition-colors`}
>
{day}
@@ -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 (
<div>
<div className="flex items-center gap-1.5 mb-4 justify-between">
<span className="font-semibold text-sm text-[#1a1a1a]">
<span className="font-semibold text-md text-[#1a1a1a]">
Timeline
</span>
<ArrowDownNarrowWide className="w-5 h-5 text-gray-500"/>
@@ -29,7 +29,7 @@ export default function ProjectTimeline({ tasks }: { tasks: Task[] }) {
<li key={idx} className="relative mb-6 list-none">
{/* Dot */}
<div
className={`absolute -left-4 top-0.5 w-2.5 h-2.5 rounded-full border-2 border-white ${active ? 'bg-[#C0392B]' : 'bg-[#ccc]'
className={`absolute -left-5 top-0.5 w-3 h-3 rounded-full border-2 border-white ${active ? 'bg-[#C0392B]' : 'bg-[#ccc]'
} ${isToday ? 'shadow-md' : ''}`}
/>
<div
@@ -1,5 +1,5 @@
import { useState, useRef } from "react";
import { FileText, UploadCloud, Trash2, X, FileUp } from "lucide-react";
import { FileText, UploadCloud, X, FileUp } from "lucide-react";
import { LuSendHorizontal } from "react-icons/lu";
interface TaskFormFileProps {