WFDASHDRIVER-APP/components/ProblemModal.tsx

174 lines
6.1 KiB
TypeScript
Raw Normal View History

'use client';
import { useState } from 'react';
import { OrderItem, PROBLEM_TYPES } from '@/lib/types';
import { cn } from '@/lib/utils';
import { X, Camera, AlertTriangle } from 'lucide-react';
interface ProblemModalProps {
item: OrderItem | null;
isOpen: boolean;
onClose: () => void;
onConfirm: (item: OrderItem, problemType: string, description: string, photo?: File) => void;
}
export default function ProblemModal({
item,
isOpen,
onClose,
onConfirm,
}: ProblemModalProps) {
const [problemType, setProblemType] = useState('');
const [description, setDescription] = useState('');
const [photo, setPhoto] = useState<File | null>(null);
const [error, setError] = useState('');
if (!isOpen || !item) return null;
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setError('');
if (!problemType) {
setError('Please select a problem type');
return;
}
if (!description.trim()) {
setError('Please describe the problem');
return;
}
onConfirm(item, problemType, description, photo || undefined);
setProblemType('');
setDescription('');
setPhoto(null);
setError('');
};
return (
<div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center">
<div className="absolute inset-0 bg-black/50 modal-overlay" onClick={onClose} />
<div className="relative bg-white bottom-sheet w-full max-w-md p-6 animate-slide-up max-h-[90vh] overflow-y-auto custom-scrollbar">
{/* Drag indicator */}
<div className="sm:hidden flex justify-center mb-4">
<div className="w-10 h-1 bg-gray-300 rounded-full" />
</div>
<div className="flex items-center justify-between mb-5">
<div className="flex items-center gap-2.5">
<div className="w-8 h-8 bg-red-50 rounded-xl flex items-center justify-center">
<AlertTriangle size={18} className="text-red-600" />
</div>
<h2 className="text-lg font-bold text-gray-900">Report Problem</h2>
</div>
<button
onClick={onClose}
className="p-2 rounded-xl hover:bg-gray-100 active:bg-gray-200 transition-colors"
>
<X size={18} className="text-gray-400" />
</button>
</div>
{/* Item info */}
<div className="mb-5 p-4 bg-red-50 border border-red-100 rounded-xl">
<p className="text-sm font-semibold text-gray-900 truncate">{item.description}</p>
<p className="text-xs text-gray-500 mt-1">
{item.expand?.supplier?.suppliername || 'Unknown Supplier'}
</p>
</div>
<form onSubmit={handleSubmit} className="space-y-5">
{/* Problem type */}
<div>
<label className="block text-sm font-semibold text-gray-700 mb-2">
What went wrong? *
</label>
<div className="space-y-2">
{PROBLEM_TYPES.map((type) => (
<button
key={type.value}
type="button"
onClick={() => { setProblemType(type.value); setError(''); }}
className={cn(
'w-full py-3 px-4 rounded-xl text-sm text-left border-2 transition-all',
'touch-manipulation press-feedback-sm',
problemType === type.value
? 'border-red-500 bg-red-50 text-red-700 font-semibold'
: 'border-gray-150 bg-white text-gray-700 active:border-gray-300'
)}
>
{type.label}
</button>
))}
</div>
</div>
{/* Description */}
<div>
<label className="block text-sm font-semibold text-gray-700 mb-2">
Details *
</label>
<textarea
value={description}
onChange={(e) => { setDescription(e.target.value); setError(''); }}
className="w-full p-3 text-sm bg-gray-50 border border-gray-200 rounded-xl focus:ring-2 focus:ring-red-500/30 focus:border-red-500 focus:bg-white transition-all resize-none selectable"
rows={3}
placeholder="Describe the problem in detail..."
autoFocus
/>
</div>
{/* Photo */}
<div>
<label className="block text-sm font-semibold text-gray-700 mb-2">
Photo (optional)
</label>
<label
htmlFor="problem-photo"
className={cn(
'flex items-center justify-center gap-2 py-3 px-4 rounded-xl border-2 border-dashed cursor-pointer',
'transition-all touch-manipulation press-feedback-sm',
photo
? 'border-green-400 bg-green-50 text-green-700'
: 'border-gray-200 bg-gray-50 text-gray-500 active:border-gray-400'
)}
>
<Camera size={20} />
<span className="text-sm font-medium">
{photo ? 'Photo attached' : 'Take or choose photo'}
</span>
<input
type="file"
accept="image/*"
capture="environment"
onChange={(e) => setPhoto(e.target.files?.[0] || null)}
className="hidden"
id="problem-photo"
/>
</label>
</div>
{/* Error */}
{error && (
<div className="p-3 bg-red-50 border border-red-100 rounded-xl animate-fade-in">
<p className="text-xs text-red-600 font-medium">{error}</p>
</div>
)}
{/* Submit */}
<button
type="submit"
className={cn(
'w-full py-4 px-4 rounded-xl text-white font-semibold text-[15px]',
'bg-red-500 active:bg-red-600 transition-all shadow-lg shadow-red-500/25',
'touch-manipulation press-feedback'
)}
>
Report Problem
</button>
</form>
</div>
</div>
);
}