Public Access
fix: wire up 'Send Vote Email' button to POST /admin/orchestrate/email
- Add triggerOrchestrate() to API client calling POST /admin/orchestrate/{step}
- Replace dead <button> in Dashboard with VoteEmailButton component:
onClick calls triggerOrchestrate('email'), shows toast spinner + success/error
This commit is contained in:
@@ -64,6 +64,7 @@ export const mealPlannerApi = {
|
||||
getMealPlans: (params?: any) => api.get('/admin/meal-plans', { params }),
|
||||
getStats: () => api.get('/admin/stats'),
|
||||
testEmail: (email: string) => api.post('/admin/test-email', null, { params: { email } }),
|
||||
triggerOrchestrate: (step: string, weekStart?: string) => api.post(`/admin/orchestrate/${step}`, null, { params: { week_start: weekStart } }),
|
||||
},
|
||||
|
||||
feedback: {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { CookingPot, CalendarDays, ShoppingCart, ChevronRight, Sparkles } from 'lucide-react'
|
||||
import { CookingPot, CalendarDays, ShoppingCart, ChevronRight, Sparkles, Loader2 } from 'lucide-react'
|
||||
import toast from 'react-hot-toast'
|
||||
import { mealPlannerApi } from '../api'
|
||||
import type { MealPlan, MealPlanItem } from '../types'
|
||||
import { Badge } from '../components/ui/Badge'
|
||||
@@ -129,6 +131,34 @@ function DashboardSkeleton() {
|
||||
)
|
||||
}
|
||||
|
||||
function VoteEmailButton() {
|
||||
const [sendingVoteEmail, setSendingVoteEmail] = useState(false)
|
||||
|
||||
async function handleSend() {
|
||||
setSendingVoteEmail(true)
|
||||
try {
|
||||
const res = await mealPlannerApi.admin.triggerOrchestrate('email')
|
||||
const status = res.data?.status || res.data?.message || 'sent'
|
||||
toast.success(status)
|
||||
} catch (err: any) {
|
||||
toast.error(err?.response?.data?.detail || 'Failed to send vote emails')
|
||||
} finally {
|
||||
setSendingVoteEmail(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={handleSend}
|
||||
disabled={sendingVoteEmail}
|
||||
className="inline-flex items-center gap-1 text-sm font-medium text-primary-600 hover:text-primary-700 transition-colors text-left disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{sendingVoteEmail ? <Loader2 className="w-4 h-4 animate-spin" /> : <ChevronRight className="w-4 h-4" />}
|
||||
{sendingVoteEmail ? 'Sending...' : 'Send Vote Email'}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Dashboard() {
|
||||
const { data: mealPlan, isLoading } = useQuery<MealPlan | null>({
|
||||
queryKey: ['mealPlan'],
|
||||
@@ -251,9 +281,7 @@ export default function Dashboard() {
|
||||
>
|
||||
Manage Pantry <ChevronRight className="w-4 h-4" />
|
||||
</Link>
|
||||
<button className="inline-flex items-center gap-1 text-sm font-medium text-primary-600 hover:text-primary-700 transition-colors text-left">
|
||||
Send Vote Email <ChevronRight className="w-4 h-4" />
|
||||
</button>
|
||||
<VoteEmailButton />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user