Apply full refactor updates plus pipeline/email UX confirmations
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m33s
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m33s
This commit is contained in:
@@ -18,6 +18,7 @@ import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Checkbox } from '@/components/ui/checkbox'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import {
|
||||
Select,
|
||||
@@ -103,6 +104,7 @@ const fileTypeIcons: Record<string, React.ReactNode> = {
|
||||
function EditProjectContent({ projectId }: { projectId: string }) {
|
||||
const router = useRouter()
|
||||
const [tagInput, setTagInput] = useState('')
|
||||
const [statusNotificationConfirmed, setStatusNotificationConfirmed] = useState(false)
|
||||
|
||||
// Fetch project data
|
||||
const { data: project, isLoading } = trpc.project.get.useQuery({
|
||||
@@ -172,6 +174,24 @@ function EditProjectContent({ projectId }: { projectId: string }) {
|
||||
}, [project, form])
|
||||
|
||||
const tags = form.watch('tags')
|
||||
const selectedStatus = form.watch('status')
|
||||
const previousStatus = (project?.status ?? 'SUBMITTED') as UpdateProjectForm['status']
|
||||
const statusTriggersNotifications = ['SEMIFINALIST', 'FINALIST', 'REJECTED'].includes(selectedStatus)
|
||||
const requiresStatusNotificationConfirmation = Boolean(
|
||||
project && selectedStatus !== previousStatus && statusTriggersNotifications
|
||||
)
|
||||
const notificationRecipientEmails = Array.from(
|
||||
new Set(
|
||||
(project?.teamMembers ?? [])
|
||||
.map((member) => member.user?.email?.toLowerCase().trim() ?? '')
|
||||
.filter((email) => email.length > 0)
|
||||
)
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setStatusNotificationConfirmed(false)
|
||||
form.clearErrors('status')
|
||||
}, [selectedStatus, form])
|
||||
|
||||
// Add tag
|
||||
const addTag = useCallback(() => {
|
||||
@@ -194,6 +214,14 @@ function EditProjectContent({ projectId }: { projectId: string }) {
|
||||
)
|
||||
|
||||
const onSubmit = async (data: UpdateProjectForm) => {
|
||||
if (requiresStatusNotificationConfirmation && !statusNotificationConfirmed) {
|
||||
form.setError('status', {
|
||||
type: 'manual',
|
||||
message: 'Confirm participant notifications before saving this status change.',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
await updateProject.mutateAsync({
|
||||
id: projectId,
|
||||
title: data.title,
|
||||
@@ -370,6 +398,39 @@ function EditProjectContent({ projectId }: { projectId: string }) {
|
||||
<SelectItem value="REJECTED">Rejected</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{requiresStatusNotificationConfirmation && (
|
||||
<div className="space-y-2 rounded-md border bg-muted/20 p-3">
|
||||
<p className="text-xs font-medium">
|
||||
Participant Notification Check
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Saving this status will send automated notifications.
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Recipients ({notificationRecipientEmails.length}):{' '}
|
||||
{notificationRecipientEmails.length > 0
|
||||
? notificationRecipientEmails.slice(0, 8).join(', ')
|
||||
: 'No linked participant accounts found'}
|
||||
{notificationRecipientEmails.length > 8 ? ', ...' : ''}
|
||||
</p>
|
||||
<div className="flex items-start gap-2">
|
||||
<Checkbox
|
||||
id="confirm-status-notifications"
|
||||
checked={statusNotificationConfirmed}
|
||||
onCheckedChange={(checked) => {
|
||||
const confirmed = checked === true
|
||||
setStatusNotificationConfirmed(confirmed)
|
||||
if (confirmed) {
|
||||
form.clearErrors('status')
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<FormLabel htmlFor="confirm-status-notifications" className="text-sm font-normal leading-5">
|
||||
I verified participant recipients and approve sending automated notifications.
|
||||
</FormLabel>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
@@ -557,7 +618,10 @@ function EditProjectContent({ projectId }: { projectId: string }) {
|
||||
<Button type="button" variant="outline" asChild>
|
||||
<Link href={`/admin/projects/${projectId}`}>Cancel</Link>
|
||||
</Button>
|
||||
<Button type="submit" disabled={isPending}>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isPending || (requiresStatusNotificationConfirmation && !statusNotificationConfirmed)}
|
||||
>
|
||||
{updateProject.isPending && (
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user