Files
internify-fe/src/Pages/internify/intern/components/HomeCalendar.tsx
T
Kemas M. Aryadary Rasyad e59e63a21e feat: Refactor mentor components and implement project management features
- Removed unused imports and interfaces in HomeProjectList component.
- Added ArrowDownNarrowWide icon to ProjectTimeline component for visual enhancement.
- Updated layout imports to reflect new component structure.
- Created BaseProjectsPage for mentor to manage projects with navigation.
- Introduced MentorCertificatePage as a placeholder for future certificate functionality.
- Deleted obsolete HomeMentorPage and replaced it with HomePage for mentor dashboard.
- Added InternsPage and updated MentorInternPage for better intern management.
- Implemented ProjectForumTab and ProjectsInternTab for project details and intern listings.
- Developed TaskTab for task management within projects.
- Created SidebarMentor for navigation in mentor dashboard.
- Enhanced login functionality with user role-based navigation.
- Updated mockData to include task submission counts and certificate data structure.
- Added new assets for certificate representation.
2026-06-05 14:33:03 +07:00

181 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from 'react'
import { ChevronLeft, ChevronRight } from 'lucide-react'
interface Deadline {
date: number
month: number
year: number
label: string
}
const DEADLINES: Deadline[] = [
{ date: 4, month: 4, year: 2025, label: 'Laporan Progress 1 Internify– 4 May' },
{ date: 5, month: 4, year: 2025, label: 'Laporan Progress 1 Internify– 4 May' },
]
const DAY_LABELS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']
const MONTH_NAMES = [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December',
]
function getDaysInMonth(year: number, month: number) {
return new Date(year, month + 1, 0).getDate()
}
function getFirstDayOfMonth(year: number, month: number) {
return new Date(year, month, 1).getDay()
}
const HomeCalendar = () => {
const today = new Date()
const [currentYear, setCurrentYear] = useState(2025)
const [currentMonth, setCurrentMonth] = useState(4) // May = 4 (0-indexed)
const daysInMonth = getDaysInMonth(currentYear, currentMonth)
const firstDay = getFirstDayOfMonth(currentYear, currentMonth)
const prevMonth = () => {
if (currentMonth === 0) {
setCurrentMonth(11)
setCurrentYear(y => y - 1)
} else {
setCurrentMonth(m => m - 1)
}
}
const nextMonth = () => {
if (currentMonth === 11) {
setCurrentMonth(0)
setCurrentYear(y => y + 1)
} else {
setCurrentMonth(m => m + 1)
}
}
const isToday = (day: number) =>
day === today.getDate() &&
currentMonth === today.getMonth() &&
currentYear === today.getFullYear()
const hasDeadline = (day: number) =>
DEADLINES.some(d => d.date === day && d.month === currentMonth && d.year === currentYear)
const upcomingDeadlines = DEADLINES.filter(
d => d.month === currentMonth && d.year === currentYear
)
// Previous month trailing days
const prevMonthDays = getDaysInMonth(currentYear, currentMonth - 1 < 0 ? 11 : currentMonth - 1)
const trailingDays = Array.from({ length: firstDay }, (_, i) => prevMonthDays - firstDay + 1 + i)
// Current month days
const currentDays = Array.from({ length: daysInMonth }, (_, i) => i + 1)
// Next month leading days
const totalCells = Math.ceil((firstDay + daysInMonth) / 7) * 7
const leadingDays = Array.from({ length: totalCells - firstDay - daysInMonth }, (_, i) => i + 1)
// Bold dates (weekends or special)
const isBold = (day: number) => {
const d = new Date(currentYear, currentMonth, day).getDay()
return d === 0 || d === 6 // Sun or Sat
}
return (
<div className=" px-13 py-5 border border-gray-200 rounded-2xl">
{/* Header */}
<div className="flex items-center justify-between mb-4">
<h2 className="text-base font-semibold text-gray-800">
{MONTH_NAMES[currentMonth]} {currentYear}
</h2>
<div className="flex items-center gap-1">
<button
onClick={prevMonth}
className="p-1 rounded hover:bg-gray-100 transition-colors"
aria-label="Previous month"
>
<ChevronLeft className="w-4 h-4 text-gray-500" />
</button>
<button
onClick={nextMonth}
className="p-1 rounded hover:bg-gray-100 transition-colors"
aria-label="Next month"
>
<ChevronRight className="w-4 h-4 text-gray-500" />
</button>
</div>
</div>
{/* Day labels */}
<div className="grid grid-cols-7 mb-1">
{DAY_LABELS.map(day => (
<div key={day} className="text-center text-xs text-gray-400 font-medium py-1">
{day}
</div>
))}
</div>
{/* Calendar grid */}
<div className="grid grid-cols-7">
{/* Trailing days from prev month */}
{trailingDays.map(day => (
<div key={`prev-${day}`} className="text-center py-2">
<span className="text-xs text-gray-300">{day}</span>
</div>
))}
{/* Current month days */}
{currentDays.map(day => (
<div key={day} className="flex justify-center items-center py-1 px-4">
{isToday(day) ? (
<span className="w-8 h-7 flex items-center justify-center rounded bg-red-800 text-white text-xs font-semibold">
{day}
</span>
) : (
<span
className={`w-full h-7 flex items-center justify-center text-xs rounded
${isBold(day) ? 'font-bold text-gray-800' : 'text-gray-700'}
${hasDeadline(day) ? 'bg-red-700 text-white' : ''}
hover:bg-gray-100 cursor-pointer transition-colors`}
>
{day}
</span>
)}
</div>
))}
{/* Leading days from next month */}
{leadingDays.map(day => (
<div key={`next-${day}`} className="text-center py-2">
<span className="text-xs text-gray-300">{day}</span>
</div>
))}
</div>
{/* Divider */}
<hr className="my-3 border-gray-100" />
{/* Upcoming Deadlines */}
<div>
<p className="text-[10px] font-semibold text-gray-400 uppercase tracking-widest mb-2">
Upcoming Deadlines
</p>
{upcomingDeadlines.length > 0 ? (
<ul className="flex flex-col gap-1">
{upcomingDeadlines.map((d, i) => (
<li key={i} className="flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-red-600 flex-shrink-0" />
<span className="text-xs text-gray-600">{d.label}</span>
</li>
))}
</ul>
) : (
<p className="text-sm text-gray-400">No upcoming deadlines this month.</p>
)}
</div>
</div>
)
}
export default HomeCalendar