inogen/app/components/dashboard/projects/project-detail.tsx

355 lines
15 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 React from "react";
import { DashboardLayout } from "../layout";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { Button } from "~/components/ui/button";
import { Badge } from "~/components/ui/badge";
import {
ArrowRight,
Calendar,
User,
Users,
DollarSign,
Clock,
FileText,
Edit,
Trash2,
} from "lucide-react";
interface ProjectDetailProps {
projectId: string;
}
// Mock project data
const mockProject = {
id: 1,
name: "پروژه توسعه اپلیکیشن موبایل",
manager: "علی احمدی",
team: "تیم توسعه موبایل",
status: "در حال انجام",
priority: "بالا",
startDate: "1403/01/15",
endDate: "1403/06/30",
budget: "500,000,000",
progress: 65,
description: "این پروژه شامل توسعه یک اپلیکیشن موبایل کراس پلتفرم برای مدیریت پروژه‌ها و وظایف می‌باشد. اپلیکیشن باید قابلیت‌های مختلفی از جمله مدیریت کاربران، گزارش‌گیری و نوتیفیکیشن را داشته باشد.",
teamMembers: [
{ id: 1, name: "علی احمدی", role: "مدیر پروژه", avatar: "AA" },
{ id: 2, name: "سارا کریمی", role: "توسعه‌دهنده فرانت‌اند", avatar: "SK" },
{ id: 3, name: "محمد رضایی", role: "توسعه‌دهنده بک‌اند", avatar: "MR" },
{ id: 4, name: "فاطمه موسوی", role: "طراح UI/UX", avatar: "FM" },
],
milestones: [
{ id: 1, title: "تحلیل نیازمندی‌ها", status: "تکمیل شده", date: "1403/01/30" },
{ id: 2, title: "طراحی رابط کاربری", status: "تکمیل شده", date: "1403/02/15" },
{ id: 3, title: "توسعه بک‌اند", status: "در حال انجام", date: "1403/04/01" },
{ id: 4, title: "توسعه فرانت‌اند", status: "در حال انجام", date: "1403/05/01" },
{ id: 5, title: "تست و رفع باگ", status: "در انتظار", date: "1403/06/01" },
{ id: 6, title: "انتشار نهایی", status: "در انتظار", date: "1403/06/30" },
],
tasks: [
{ id: 1, title: "پیاده‌سازی سیستم احراز هویت", assignee: "محمد رضایی", status: "در حال انجام", priority: "بالا" },
{ id: 2, title: "طراحی صفحه داشبورد", assignee: "سارا کریمی", status: "تکمیل شده", priority: "متوسط" },
{ id: 3, title: "توسعه API گزارش‌گیری", assignee: "محمد رضایی", status: "در انتظار", priority: "بالا" },
{ id: 4, title: "طراحی آیکون‌های اپلیکیشن", assignee: "فاطمه موسوی", status: "در حال انجام", priority: "پایین" },
],
};
const statusColors = {
"در حال انجام": "info",
"تکمیل شده": "success",
"در انتظار": "warning",
"لغو شده": "destructive",
} as const;
const priorityColors = {
"بالا": "destructive",
"متوسط": "warning",
"پایین": "secondary",
} as const;
export function ProjectDetail({ projectId }: ProjectDetailProps) {
const project = mockProject; // In real app, fetch by projectId
return (
<DashboardLayout>
<div className="p-6 space-y-6">
{/* Breadcrumb */}
<div className="flex items-center space-x-2 text-sm text-gray-500 dark:text-gray-400">
<Button variant="ghost" size="sm" className="font-persian p-0 h-auto">
پروژهها
</Button>
<ArrowRight className="w-4 h-4" />
<span className="font-persian text-gray-900 dark:text-white">
جزئیات پروژه
</span>
</div>
{/* Project Header */}
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4">
<div>
<h1 className="text-3xl font-bold text-gray-900 dark:text-white font-persian">
{project.name}
</h1>
<p className="text-gray-600 dark:text-gray-400 font-persian mt-2">
{project.description}
</p>
</div>
<div className="flex gap-2">
<Button variant="outline" className="font-persian">
<Edit className="w-4 h-4 ml-2" />
ویرایش پروژه
</Button>
<Button variant="destructive" className="font-persian">
<Trash2 className="w-4 h-4 ml-2" />
حذف پروژه
</Button>
</div>
</div>
{/* Project Stats */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<Card>
<CardContent className="p-4">
<div className="flex items-center space-x-2">
<div className="p-2 bg-blue-100 rounded-lg dark:bg-blue-900">
<Calendar className="w-5 h-5 text-blue-600 dark:text-blue-400" />
</div>
<div className="flex-1 text-right">
<p className="text-sm text-gray-600 dark:text-gray-400 font-persian">تاریخ شروع</p>
<p className="text-lg font-bold text-gray-900 dark:text-white font-persian">
{project.startDate}
</p>
</div>
</div>
</CardContent>
</Card>
<Card>
<CardContent className="p-4">
<div className="flex items-center space-x-2">
<div className="p-2 bg-green-100 rounded-lg dark:bg-green-900">
<Clock className="w-5 h-5 text-green-600 dark:text-green-400" />
</div>
<div className="flex-1 text-right">
<p className="text-sm text-gray-600 dark:text-gray-400 font-persian">تاریخ پایان</p>
<p className="text-lg font-bold text-gray-900 dark:text-white font-persian">
{project.endDate}
</p>
</div>
</div>
</CardContent>
</Card>
<Card>
<CardContent className="p-4">
<div className="flex items-center space-x-2">
<div className="p-2 bg-yellow-100 rounded-lg dark:bg-yellow-900">
<DollarSign className="w-5 h-5 text-yellow-600 dark:text-yellow-400" />
</div>
<div className="flex-1 text-right">
<p className="text-sm text-gray-600 dark:text-gray-400 font-persian">بودجه</p>
<p className="text-lg font-bold text-gray-900 dark:text-white font-persian">
{project.budget} ریال
</p>
</div>
</div>
</CardContent>
</Card>
<Card>
<CardContent className="p-4">
<div className="flex items-center space-x-2">
<div className="p-2 bg-purple-100 rounded-lg dark:bg-purple-900">
<FileText className="w-5 h-5 text-purple-600 dark:text-purple-400" />
</div>
<div className="flex-1 text-right">
<p className="text-sm text-gray-600 dark:text-gray-400 font-persian">پیشرفت</p>
<p className="text-lg font-bold text-gray-900 dark:text-white font-persian">
{project.progress}%
</p>
</div>
</div>
</CardContent>
</Card>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* Project Details */}
<div className="lg:col-span-2 space-y-6">
{/* Progress Bar */}
<Card>
<CardHeader>
<CardTitle className="font-persian">پیشرفت پروژه</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex justify-between items-center">
<span className="text-sm font-medium text-gray-500 dark:text-gray-400 font-persian">
{project.progress}% تکمیل شده
</span>
<div className="flex items-center gap-2">
<Badge variant={statusColors[project.status as keyof typeof statusColors]} className="font-persian">
{project.status}
</Badge>
<Badge variant={priorityColors[project.priority as keyof typeof priorityColors]} className="font-persian">
اولویت {project.priority}
</Badge>
</div>
</div>
<div className="w-full bg-gray-200 rounded-full h-3 dark:bg-gray-700">
<div
className="bg-gradient-to-r from-blue-500 to-blue-600 h-3 rounded-full transition-all duration-500"
style={{ width: `${project.progress}%` }}
></div>
</div>
</div>
</CardContent>
</Card>
{/* Milestones */}
<Card>
<CardHeader>
<CardTitle className="font-persian">مراحل پروژه</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{project.milestones.map((milestone) => (
<div key={milestone.id} className="flex items-center justify-between p-3 border rounded-lg dark:border-gray-700">
<div className="flex items-center space-x-3">
<div
className={`w-3 h-3 rounded-full ${
milestone.status === "تکمیل شده"
? "bg-green-500"
: milestone.status === "در حال انجام"
? "bg-blue-500"
: "bg-gray-300"
}`}
></div>
<div className="text-right">
<p className="font-medium text-gray-900 dark:text-white font-persian">
{milestone.title}
</p>
<p className="text-sm text-gray-500 dark:text-gray-400 font-persian">
{milestone.date}
</p>
</div>
</div>
<Badge
variant={statusColors[milestone.status as keyof typeof statusColors]}
className="font-persian"
>
{milestone.status}
</Badge>
</div>
))}
</div>
</CardContent>
</Card>
{/* Recent Tasks */}
<Card>
<CardHeader>
<CardTitle className="font-persian">وظایف اخیر</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-3">
{project.tasks.map((task) => (
<div key={task.id} className="flex items-center justify-between p-3 border rounded-lg dark:border-gray-700">
<div className="text-right">
<p className="font-medium text-gray-900 dark:text-white font-persian">
{task.title}
</p>
<p className="text-sm text-gray-500 dark:text-gray-400 font-persian">
مسئول: {task.assignee}
</p>
</div>
<div className="flex items-center gap-2">
<Badge variant={statusColors[task.status as keyof typeof statusColors]} className="font-persian">
{task.status}
</Badge>
<Badge variant={priorityColors[task.priority as keyof typeof priorityColors]} className="font-persian">
{task.priority}
</Badge>
</div>
</div>
))}
</div>
</CardContent>
</Card>
</div>
{/* Sidebar */}
<div className="space-y-6">
{/* Project Info */}
<Card>
<CardHeader>
<CardTitle className="font-persian">اطلاعات پروژه</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center space-x-2">
<User className="w-4 h-4 text-gray-500" />
<div className="text-right">
<p className="text-sm text-gray-500 dark:text-gray-400 font-persian">مدیر پروژه</p>
<p className="font-medium text-gray-900 dark:text-white font-persian">
{project.manager}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<Users className="w-4 h-4 text-gray-500" />
<div className="text-right">
<p className="text-sm text-gray-500 dark:text-gray-400 font-persian">تیم</p>
<p className="font-medium text-gray-900 dark:text-white font-persian">
{project.team}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<Calendar className="w-4 h-4 text-gray-500" />
<div className="text-right">
<p className="text-sm text-gray-500 dark:text-gray-400 font-persian">مدت زمان</p>
<p className="font-medium text-gray-900 dark:text-white font-persian">
{project.startDate} تا {project.endDate}
</p>
</div>
</div>
</CardContent>
</Card>
{/* Team Members */}
<Card>
<CardHeader>
<CardTitle className="font-persian">اعضای تیم</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-3">
{project.teamMembers.map((member) => (
<div key={member.id} className="flex items-center space-x-3">
<div className="w-10 h-10 bg-gradient-to-r from-blue-500 to-purple-500 rounded-full flex items-center justify-center text-white font-medium text-sm">
{member.avatar}
</div>
<div className="text-right">
<p className="font-medium text-gray-900 dark:text-white font-persian">
{member.name}
</p>
<p className="text-sm text-gray-500 dark:text-gray-400 font-persian">
{member.role}
</p>
</div>
</div>
))}
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</DashboardLayout>
);
}
export default ProjectDetail;