Complete frontend implementation with: - Next.js 16 with App Router and TypeScript - Tailwind CSS v4 with custom violet theme - shadcn/ui components with Lucide React icons - Landing page with hero, services, pricing, testimonials, FAQ - Service selection page with toggle - Login/Register pages with social auth UI - Multi-step checkout flow - Client dashboard with stats, projects, support tickets - Billing page with subscription, payment methods, invoices - All mock data and TypeScript types 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
83 lines
3.0 KiB
TypeScript
83 lines
3.0 KiB
TypeScript
'use client'
|
|
import { ArrowRight, Circle, CircleCheck } from 'lucide-react'
|
|
|
|
import Link from 'next/link'
|
|
import { Card, CardContent } from '@/components/ui/card'
|
|
import { Badge } from '@/components/ui/badge'
|
|
import { Progress } from '@/components/ui/progress'
|
|
import type { Project } from '@/lib/types'
|
|
|
|
interface ProjectCardProps {
|
|
project: Project
|
|
}
|
|
|
|
const statusColors: Record<Project['status'], string> = {
|
|
discovery: 'bg-blue-500/10 text-blue-400',
|
|
design: 'bg-purple-500/10 text-purple-400',
|
|
development: 'bg-yellow-500/10 text-yellow-400',
|
|
content: 'bg-orange-500/10 text-orange-400',
|
|
testing: 'bg-cyan-500/10 text-cyan-400',
|
|
completed: 'bg-emerald-500/10 text-emerald-400',
|
|
}
|
|
|
|
export function ProjectCard({ project }: ProjectCardProps) {
|
|
return (
|
|
<Link href={`/dashboard/projects/${project.id}`}>
|
|
<Card className="glow-card bg-card border-border hover:border-primary transition-all duration-300">
|
|
<CardContent className="p-6">
|
|
{/* Thumbnail */}
|
|
<div
|
|
className="w-full h-40 rounded-lg mb-4 bg-cover bg-center"
|
|
style={{ backgroundImage: `url(${project.thumbnail})` }}
|
|
/>
|
|
|
|
{/* Title and Status */}
|
|
<div className="flex items-start justify-between mb-3">
|
|
<div className="flex-1">
|
|
<h3 className="font-bold text-foreground text-lg mb-1">{project.title}</h3>
|
|
<p className="text-sm text-muted-foreground line-clamp-2">
|
|
{project.description}
|
|
</p>
|
|
</div>
|
|
<Badge className={`ml-2 ${statusColors[project.status]}`}>
|
|
{project.status}
|
|
</Badge>
|
|
</div>
|
|
|
|
{/* Progress */}
|
|
<div className="mb-4">
|
|
<div className="flex justify-between text-sm mb-2">
|
|
<span className="text-muted-foreground">Progress</span>
|
|
<span className="text-foreground font-medium">{project.progress}%</span>
|
|
</div>
|
|
<Progress value={project.progress} className="h-2" />
|
|
</div>
|
|
|
|
{/* Stages */}
|
|
<div className="flex items-center gap-2 text-xs text-muted-foreground">
|
|
{project.stages.map((stage, index) => (
|
|
<div key={index} className="flex items-center gap-1">
|
|
{stage.completed ? (
|
|
<CircleCheck className="w-4 h-4 text-primary" />
|
|
) : (
|
|
<Circle className="w-4 h-4" />
|
|
)}
|
|
<span className={stage.completed ? 'text-foreground' : ''}>
|
|
{stage.name}
|
|
</span>
|
|
{index < project.stages.length - 1 && <span>→</span>}
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Updated */}
|
|
<div className="mt-4 pt-4 border-t border-border flex items-center justify-between text-xs text-muted-foreground">
|
|
<span>Updated {new Date(project.updatedAt).toLocaleDateString()}</span>
|
|
<ArrowRight className="w-4 h-4" />
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</Link>
|
|
)
|
|
}
|