feat: 공정관리 페이지 및 컴포넌트 추가
- 공정관리 목록/상세/등록/수정 페이지 구현 - ProcessListClient, ProcessDetail, ProcessForm 컴포넌트 추가 - ProcessWorkLogPreviewModal, RuleModal 추가 - MobileCard 공통 컴포넌트 추가 - WorkLogModal.tsx 개선 - .gitignore 업데이트 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
99
src/components/molecules/MobileCard.tsx
Normal file
99
src/components/molecules/MobileCard.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
'use client';
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface MobileCardDetail {
|
||||
label: string;
|
||||
value: string | ReactNode;
|
||||
}
|
||||
|
||||
interface MobileCardProps {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
description?: string;
|
||||
badge?: string;
|
||||
badgeVariant?: 'default' | 'secondary' | 'destructive' | 'outline';
|
||||
isSelected?: boolean;
|
||||
onToggle?: () => void;
|
||||
onClick?: () => void;
|
||||
details?: MobileCardDetail[];
|
||||
actions?: ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function MobileCard({
|
||||
title,
|
||||
subtitle,
|
||||
description,
|
||||
badge,
|
||||
badgeVariant = 'default',
|
||||
isSelected = false,
|
||||
onToggle,
|
||||
onClick,
|
||||
details = [],
|
||||
actions,
|
||||
className,
|
||||
}: MobileCardProps) {
|
||||
return (
|
||||
<Card
|
||||
className={cn(
|
||||
'cursor-pointer transition-colors hover:bg-muted/50',
|
||||
isSelected && 'ring-2 ring-primary',
|
||||
className
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
<CardContent className="p-4">
|
||||
<div className="flex items-start gap-3">
|
||||
{onToggle && (
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<Checkbox checked={isSelected} onCheckedChange={onToggle} />
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-1 min-w-0">
|
||||
{/* 헤더 */}
|
||||
<div className="flex items-start justify-between gap-2 mb-2">
|
||||
<div>
|
||||
<div className="font-medium truncate">{title}</div>
|
||||
{subtitle && (
|
||||
<div className="text-sm text-muted-foreground">{subtitle}</div>
|
||||
)}
|
||||
</div>
|
||||
{badge && <Badge variant={badgeVariant}>{badge}</Badge>}
|
||||
</div>
|
||||
|
||||
{/* 설명 */}
|
||||
{description && (
|
||||
<p className="text-sm text-muted-foreground mb-3 line-clamp-2">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* 상세 정보 */}
|
||||
{details.length > 0 && (
|
||||
<div className="grid grid-cols-2 gap-2 text-sm">
|
||||
{details.map((detail, index) => (
|
||||
<div key={index}>
|
||||
<span className="text-muted-foreground">{detail.label}: </span>
|
||||
<span className="font-medium">{detail.value}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 액션 */}
|
||||
{actions && (
|
||||
<div className="mt-3 pt-3 border-t" onClick={(e) => e.stopPropagation()}>
|
||||
{actions}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user