import { useState } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { useParams, Link } from 'react-router-dom'
import { Clock, Users, ChefHat, ArrowLeft, Printer, Star, AlertTriangle, MessageSquare } from 'lucide-react'
import { mealPlannerApi } from '../api'
import type { MealPlanItem, Feedback } from '../types'
import { Button } from '../components/ui/Button'
import { Badge } from '../components/ui/Badge'
import { Card, CardBody, CardHeader } from '../components/ui/Card'
import { Skeleton, SkeletonText } from '../components/ui/Skeleton'
import { Select } from '../components/ui/Select'
import { Textarea } from '../components/ui/Textarea'
import { showToast } from '../lib/toast'
const DENIAL_REASONS = [
{ value: '', label: 'Select a reason...' },
{ value: 'too_expensive', label: 'Too expensive' },
{ value: 'boring', label: 'Boring / not interesting' },
{ value: 'disliked_ingredient', label: 'Disliked ingredient' },
{ value: 'cultural', label: 'Cultural / dietary preference' },
{ value: 'other', label: 'Other' },
]
function StarRating({ value, onChange }: { value: number; onChange: (n: number) => void }) {
return (
{[1, 2, 3, 4, 5].map((n) => (
))}
)
}
function SavedRating({ rating }: { rating: number }) {
return (
{[1, 2, 3, 4, 5].map((n) => (
))}
)
}
function MealDetailSkeleton() {
return (
)
}
export default function MealDetail() {
const { id } = useParams<{ id: string }>()
const queryClient = useQueryClient()
const { data: item, isLoading } = useQuery({
queryKey: ['mealItem', id],
queryFn: () => mealPlannerApi.meals.getItem(id!).then(r => r.data),
enabled: !!id,
})
const { data: existingFeedback } = useQuery({
queryKey: ['feedback', id],
queryFn: () => mealPlannerApi.feedback.get(id!).then(r => r.data),
enabled: !!id,
})
const [rating, setRating] = useState(0)
const [neverSuggest, setNeverSuggest] = useState(false)
const [reason, setReason] = useState('')
const [text, setText] = useState('')
const [submitted, setSubmitted] = useState(false)
const [editingFeedback, setEditingFeedback] = useState(false)
const submitMutation = useMutation({
mutationFn: (payload: any) => mealPlannerApi.feedback.create(payload),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['feedback', id] })
setSubmitted(true)
setEditingFeedback(false)
showToast.success('Feedback saved!')
},
onError: () => {
showToast.error('Failed to save feedback. Please try again.')
},
})
if (isLoading) {
return
}
if (!item?.recipe) {
return (
Back to meal plan
Recipe Not Found
This meal item doesn't have an associated recipe.
)
}
const recipe = item.recipe
const feedback = existingFeedback
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
if (!id) return
submitMutation.mutate({
meal_plan_item_id: id,
rating: rating || null,
never_suggest: neverSuggest,
denial_reason: reason || null,
feedback_text: text || null,
})
}
const totalTime = recipe.total_time_minutes ??
(recipe.prep_time_minutes || 0) + (recipe.cook_time_minutes || 0)
return (
{/* Back Link */}
Back to meal plan
{/* Hero */}
{recipe.image_url ? (

) : (
)}
{recipe.name}
{recipe.description && (
{recipe.description}
)}
${item.estimated_cost?.toFixed(2) || 'N/A'}
per serving
{/* Metadata Row */}
{totalTime > 0 && (
{totalTime} min total
)}
{recipe.prep_time_minutes != null && recipe.prep_time_minutes > 0 && (
Prep {recipe.prep_time_minutes} min
)}
{recipe.cook_time_minutes != null && recipe.cook_time_minutes > 0 && (
Cook {recipe.cook_time_minutes} min
)}
{recipe.servings} servings
{recipe.cuisine_tags?.length > 0 && (
{recipe.cuisine_tags.map(tag => (
{tag}
))}
)}
{recipe.dietary_tags?.length > 0 && (
{recipe.dietary_tags.map(tag => (
{tag}
))}
)}
{/* Ingredients */}
Ingredients
{recipe.ingredients?.map((ing, idx) => (
-
{ing.quantity && `${ing.quantity} `}
{ing.unit && `${ing.unit} `}
{ing.name}
{ing.is_optional && (
(optional)
)}
))}
{/* Instructions */}
Instructions
{recipe.instructions?.map((step, idx) => (
-
{idx + 1}
{step}
))}
{/* Feedback */}
Feedback
{feedback?.rating && !editingFeedback ? (
Your rating:
{feedback.never_suggest && (
Never suggest this recipe again
)}
{feedback.denial_reason && (
Reason:{' '}
{feedback.denial_reason.replace(/_/g, ' ')}
)}
{feedback.feedback_text && (
"{feedback.feedback_text}"
)}
) : submitted && !editingFeedback ? (
Thanks for your feedback!
) : (
)}
{/* Actions */}
} onClick={() => window.print()}>
Print Recipe
)
}