Update all hooks (Projects, Tasks, Certificates), implement backend for Projects. HomePage on Mentors
This commit is contained in:
@@ -1,11 +1,6 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { } from '../../../hooks/useProjects';
|
||||
import type { Project } from '../../../types/project.types';
|
||||
|
||||
export default function ParticipantsTab({ project }: { project: Project }) {
|
||||
const { slug } = useParams<{ slug: string }>();
|
||||
const { interns, loading, error } = useProjectInterns(slug ?? "");
|
||||
import type { ProjectDetail, ProjectMember } from '../../../types/project.types';
|
||||
|
||||
export default function ParticipantsTab({ project }: { project: ProjectDetail }) {
|
||||
return (
|
||||
<div>
|
||||
{/* Mentor */}
|
||||
@@ -30,44 +25,29 @@ export default function ParticipantsTab({ project }: { project: Project }) {
|
||||
{/* Members */}
|
||||
<div>
|
||||
<h3 className="font-bold text-font-shade mb-3.5">Members</h3>
|
||||
|
||||
{loading && (
|
||||
<div className="flex flex-col gap-3">
|
||||
{[...Array(3)].map((_, i) => (
|
||||
<div key={i} className="h-10 bg-gray-100 rounded animate-pulse" />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && <p className="text-red-500 text-sm">{error}</p>}
|
||||
|
||||
{!loading && !error && interns.map((intern, idx) => (
|
||||
{project.members.map((member: ProjectMember, idx) => (
|
||||
<div
|
||||
key={intern.id}
|
||||
key={member.id}
|
||||
className={`flex items-center justify-between py-3 ${
|
||||
idx < interns.length - 1 ? 'border-b border-box-border' : ''
|
||||
idx < project.members.length - 1 ? 'border-b border-box-border' : ''
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
{intern.avatar ? (
|
||||
<img
|
||||
src={intern.avatar}
|
||||
alt={intern.full_name}
|
||||
className="w-7 h-7 rounded-full object-cover"
|
||||
/>
|
||||
{member.avatar ? (
|
||||
<img src={member.avatar} alt={member.full_name} className="w-7 h-7 rounded-full object-cover" />
|
||||
) : (
|
||||
<div className="w-7 h-7 rounded-full bg-gray-200 flex-shrink-0" />
|
||||
)}
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm text-[#333]">{intern.full_name}</span>
|
||||
<span className="text-[11px] text-gray-400">{intern.email}</span>
|
||||
<span className="text-sm text-[#333]">{member.full_name}</span>
|
||||
<span className="text-[11px] text-gray-400">{member.email}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-[13px] text-[#555] font-semibold">{intern.kelompok_peminatan}</span>
|
||||
<span className="text-[13px] text-[#555] font-semibold">{member.kelompok_peminatan}</span>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{!loading && !error && interns.length === 0 && (
|
||||
{project.members.length === 0 && (
|
||||
<p className="text-sm text-gray-400">Belum ada members.</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
// import { useProjectDetail } from '../../../hooks/useProjectDetail';
|
||||
import { useProjectDetail } from '../../../hooks/useProjects';
|
||||
import ForumTab from './ForumTab';
|
||||
import ParticipantsTab from './ParticipantTab';
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-react'
|
||||
import { useMyTasks } from '../../../../hooks/useProjects';
|
||||
//SEMENTARA USERSERVICES BELUM KUBUAT
|
||||
import api from '../../../../lib/api';
|
||||
|
||||
const DAY_LABELS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']
|
||||
const MONTH_NAMES = [
|
||||
@@ -16,19 +18,29 @@ function getFirstDayOfMonth(year: number, month: number) {
|
||||
return new Date(year, month, 1).getDay()
|
||||
}
|
||||
|
||||
const HomeCalendar = () => {
|
||||
interface roleUser {
|
||||
role: "mentor" | "intern" | "admin";
|
||||
}
|
||||
|
||||
export default function HomeCalendar() {
|
||||
const [today, setToday] = useState(new Date());
|
||||
const [role, setRole] = useState<"mentor" | "intern" | "admin" | null>(null);
|
||||
const { tasks } = useMyTasks();
|
||||
|
||||
const DEADLINES = tasks.map(task => ({
|
||||
date: new Date(task.deadline_at),
|
||||
label: task.title,
|
||||
}));
|
||||
useEffect(() => {
|
||||
api.get("/auth-api/me")
|
||||
.then((res) => setRole(res.data.data.role))
|
||||
.catch((err) => console.error("Failed to fetch user:", err));
|
||||
}, []);
|
||||
|
||||
const DEADLINES = role === "intern"
|
||||
? tasks.map(task => ({ date: new Date(task.deadline_at), label: task.title, }))
|
||||
: [];
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setToday(new Date())
|
||||
}, 60 * 1000) // update tiap 1 menit
|
||||
}, 60 * 1000)
|
||||
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
@@ -187,6 +199,4 @@ const HomeCalendar = () => {
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomeCalendar
|
||||
}
|
||||
@@ -14,7 +14,7 @@ const ProjectCard = (project: Project) => {
|
||||
const Icon = getDynamicIcon(project.project_icon);
|
||||
|
||||
|
||||
const tasksDone = -1;
|
||||
const tasksDone = 1;
|
||||
const tasksTotal = project.total_tasks;
|
||||
|
||||
return (
|
||||
|
||||
@@ -48,7 +48,7 @@ export default function SidebarIntern({ isOpen, closeSidebar }: SidebarProps) {
|
||||
{/* Brand & Tombol Close untuk Mobile */}
|
||||
<div className="flex items-center justify-between px-2 pb-10">
|
||||
<div className="flex items-center gap-2.5">
|
||||
<div className="w-9 h-9 rounded-[10px] bg-red-600 flex items-center justify-center flex-shrink-0"></div>
|
||||
<div className="w-9 h-9 rounded-[10px] bg-red flex items-center justify-center flex-shrink-0"></div>
|
||||
<div>
|
||||
<p className="text-sm font-bold text-gray-900 leading-tight">Internify</p>
|
||||
<p className="text-[11px] text-gray-400">LMS Portal</p>
|
||||
|
||||
Reference in New Issue
Block a user