mirror of
https://github.com/walkxcode/dashboard-icons.git
synced 2025-11-18 17:47:30 +01:00
feat(submissions): add experimental warning and confirmation dialog to submission form
- Replace inline warning with shared ExperimentalWarning component - Add confirmation dialog before submission to acknowledge experimental phase - Refactor submission handler to show dialog first, then process on confirmation - Warn users that submissions won't be reviewed during experimentation phase
This commit is contained in:
@@ -5,6 +5,17 @@ import { Check, FileImage, FileType, Plus, X } from "lucide-react"
|
|||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import { toast } from "sonner"
|
import { toast } from "sonner"
|
||||||
import { IconNameCombobox } from "@/components/icon-name-combobox"
|
import { IconNameCombobox } from "@/components/icon-name-combobox"
|
||||||
|
import { ExperimentalWarning } from "@/components/experimental-warning"
|
||||||
|
import {
|
||||||
|
AlertDialog,
|
||||||
|
AlertDialogAction,
|
||||||
|
AlertDialogCancel,
|
||||||
|
AlertDialogContent,
|
||||||
|
AlertDialogDescription,
|
||||||
|
AlertDialogFooter,
|
||||||
|
AlertDialogHeader,
|
||||||
|
AlertDialogTitle,
|
||||||
|
} from "@/components/ui/alert-dialog"
|
||||||
import { Badge } from "@/components/ui/badge"
|
import { Badge } from "@/components/ui/badge"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
@@ -98,6 +109,7 @@ interface FormData {
|
|||||||
|
|
||||||
export function AdvancedIconSubmissionFormTanStack() {
|
export function AdvancedIconSubmissionFormTanStack() {
|
||||||
const [filePreviews, setFilePreviews] = useState<Record<string, string>>({})
|
const [filePreviews, setFilePreviews] = useState<Record<string, string>>({})
|
||||||
|
const [showConfirmDialog, setShowConfirmDialog] = useState(false)
|
||||||
const { data: existingIcons = [] } = useExistingIconNames()
|
const { data: existingIcons = [] } = useExistingIconNames()
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
@@ -117,77 +129,84 @@ export function AdvancedIconSubmissionFormTanStack() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
setShowConfirmDialog(true)
|
||||||
const assetFiles: File[] = []
|
|
||||||
|
|
||||||
// Add base file
|
|
||||||
if (value.files.base?.[0]) {
|
|
||||||
assetFiles.push(value.files.base[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build extras object
|
|
||||||
const extras: any = {
|
|
||||||
aliases: value.aliases,
|
|
||||||
categories: value.categories,
|
|
||||||
base: value.files.base[0]?.name.split(".").pop() || "svg",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add color variants if present
|
|
||||||
if (value.files.dark?.[0] || value.files.light?.[0]) {
|
|
||||||
extras.colors = {}
|
|
||||||
if (value.files.dark?.[0]) {
|
|
||||||
extras.colors.dark = value.files.dark[0].name
|
|
||||||
assetFiles.push(value.files.dark[0])
|
|
||||||
}
|
|
||||||
if (value.files.light?.[0]) {
|
|
||||||
extras.colors.light = value.files.light[0].name
|
|
||||||
assetFiles.push(value.files.light[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add wordmark variants if present
|
|
||||||
if (value.files.wordmark?.[0] || value.files.wordmark_dark?.[0]) {
|
|
||||||
extras.wordmark = {}
|
|
||||||
if (value.files.wordmark?.[0]) {
|
|
||||||
extras.wordmark.light = value.files.wordmark[0].name
|
|
||||||
assetFiles.push(value.files.wordmark[0])
|
|
||||||
}
|
|
||||||
if (value.files.wordmark_dark?.[0]) {
|
|
||||||
extras.wordmark.dark = value.files.wordmark_dark[0].name
|
|
||||||
assetFiles.push(value.files.wordmark_dark[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create submission
|
|
||||||
const submissionData = {
|
|
||||||
name: value.iconName,
|
|
||||||
assets: assetFiles,
|
|
||||||
created_by: pb.authStore.model?.id,
|
|
||||||
status: "pending",
|
|
||||||
extras: extras,
|
|
||||||
}
|
|
||||||
|
|
||||||
await pb.collection("submissions").create(submissionData)
|
|
||||||
|
|
||||||
// Revalidate Next.js cache for community pages
|
|
||||||
await revalidateAllSubmissions()
|
|
||||||
|
|
||||||
toast.success("Icon submitted!", {
|
|
||||||
description: `Your icon "${value.iconName}" has been submitted for review`,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Reset form
|
|
||||||
form.reset()
|
|
||||||
setFilePreviews({})
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error("Submission error:", error)
|
|
||||||
toast.error("Failed to submit icon", {
|
|
||||||
description: error?.message || "Please try again later",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const handleConfirmedSubmit = async () => {
|
||||||
|
const value = form.state.values
|
||||||
|
setShowConfirmDialog(false)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const assetFiles: File[] = []
|
||||||
|
|
||||||
|
// Add base file
|
||||||
|
if (value.files.base?.[0]) {
|
||||||
|
assetFiles.push(value.files.base[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build extras object
|
||||||
|
const extras: any = {
|
||||||
|
aliases: value.aliases,
|
||||||
|
categories: value.categories,
|
||||||
|
base: value.files.base[0]?.name.split(".").pop() || "svg",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add color variants if present
|
||||||
|
if (value.files.dark?.[0] || value.files.light?.[0]) {
|
||||||
|
extras.colors = {}
|
||||||
|
if (value.files.dark?.[0]) {
|
||||||
|
extras.colors.dark = value.files.dark[0].name
|
||||||
|
assetFiles.push(value.files.dark[0])
|
||||||
|
}
|
||||||
|
if (value.files.light?.[0]) {
|
||||||
|
extras.colors.light = value.files.light[0].name
|
||||||
|
assetFiles.push(value.files.light[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add wordmark variants if present
|
||||||
|
if (value.files.wordmark?.[0] || value.files.wordmark_dark?.[0]) {
|
||||||
|
extras.wordmark = {}
|
||||||
|
if (value.files.wordmark?.[0]) {
|
||||||
|
extras.wordmark.light = value.files.wordmark[0].name
|
||||||
|
assetFiles.push(value.files.wordmark[0])
|
||||||
|
}
|
||||||
|
if (value.files.wordmark_dark?.[0]) {
|
||||||
|
extras.wordmark.dark = value.files.wordmark_dark[0].name
|
||||||
|
assetFiles.push(value.files.wordmark_dark[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create submission
|
||||||
|
const submissionData = {
|
||||||
|
name: value.iconName,
|
||||||
|
assets: assetFiles,
|
||||||
|
created_by: pb.authStore.model?.id,
|
||||||
|
status: "pending",
|
||||||
|
extras: extras,
|
||||||
|
}
|
||||||
|
|
||||||
|
await pb.collection("submissions").create(submissionData)
|
||||||
|
|
||||||
|
// Revalidate Next.js cache for community pages
|
||||||
|
await revalidateAllSubmissions()
|
||||||
|
|
||||||
|
toast.success("Icon submitted!", {
|
||||||
|
description: `Your icon "${value.iconName}" has been submitted for review`,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Reset form
|
||||||
|
form.reset()
|
||||||
|
setFilePreviews({})
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("Submission error:", error)
|
||||||
|
toast.error("Failed to submit icon", {
|
||||||
|
description: error?.message || "Please try again later",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleRemoveVariant = (variantId: string) => {
|
const handleRemoveVariant = (variantId: string) => {
|
||||||
if (variantId !== "base") {
|
if (variantId !== "base") {
|
||||||
// Remove from selected variants
|
// Remove from selected variants
|
||||||
@@ -272,6 +291,26 @@ export function AdvancedIconSubmissionFormTanStack() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-4xl mx-auto">
|
<div className="max-w-4xl mx-auto">
|
||||||
|
<ExperimentalWarning message="This icon submission form is currently in an experimentation phase. Submissions will not be reviewed or processed at this time. We're gathering feedback to improve the experience." />
|
||||||
|
|
||||||
|
<AlertDialog open={showConfirmDialog} onOpenChange={setShowConfirmDialog}>
|
||||||
|
<AlertDialogContent>
|
||||||
|
<AlertDialogHeader>
|
||||||
|
<AlertDialogTitle>Confirm Submission</AlertDialogTitle>
|
||||||
|
<AlertDialogDescription>
|
||||||
|
This icon submission form is a work-in-progress and is currently in an experimentation phase. Your submission will not be reviewed or processed at this time. We're using this to gather feedback and improve the experience.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Do you still want to proceed with submitting your icon?
|
||||||
|
</AlertDialogDescription>
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogFooter>
|
||||||
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||||
|
<AlertDialogAction onClick={handleConfirmedSubmit}>Yes, Submit Anyway</AlertDialogAction>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialog>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|||||||
Reference in New Issue
Block a user