From 544890c84298b11b6c296ddddf108ca2ba5e408c Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Thu, 3 Apr 2025 19:14:50 -0400 Subject: [PATCH 1/2] refactor: improve risk chart components with enhanced visual clarity and structure - Updated visual order definitions for likelihood and impact in InherentRiskVendorChart and ResidualRiskVendorChart for better clarity. - Enhanced axis labels for improved readability. - Streamlined grid layout and rendering logic to optimize performance and maintainability. - Adjusted styling for responsive design and consistency across components. --- .../components/inherent-risk-vendor-chart.tsx | 199 ++++++++---------- .../components/residual-risk-vendor-chart.tsx | 199 ++++++++---------- 2 files changed, 170 insertions(+), 228 deletions(-) diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk-vendor-chart.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk-vendor-chart.tsx index 5f6204cb5c..92bad86193 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk-vendor-chart.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk-vendor-chart.tsx @@ -70,7 +70,7 @@ export function InherentRiskVendorChart({ vendor }: InherentRiskChartProps) { // Get color based on risk level const riskColor = RISK_COLORS[riskLevel as keyof typeof RISK_COLORS]; - // Define the visual order of likelihood for rendering + // Define the visual order for rows and columns const VISUAL_LIKELIHOOD_ORDER: Likelihood[] = [ Likelihood.very_likely, Likelihood.likely, @@ -78,16 +78,22 @@ export function InherentRiskVendorChart({ vendor }: InherentRiskChartProps) { Likelihood.unlikely, Likelihood.very_unlikely, ]; + const VISUAL_IMPACT_ORDER: Impact[] = [ + Impact.insignificant, + Impact.minor, + Impact.moderate, + Impact.major, + Impact.severe, + ]; - // We'll determine the active cell while building the grid const yAxisLabels = [ - "V.Likely", // Corresponds to VISUAL_LIKELIHOOD_ORDER[0] + "Very Likely", // Corresponds to VISUAL_LIKELIHOOD_ORDER[0] "Likely", "Possible", "Unlikely", - "V.Unlikely", // Corresponds to VISUAL_LIKELIHOOD_ORDER[4] + "Very Unlikely", // Corresponds to VISUAL_LIKELIHOOD_ORDER[4] ]; - const xAxisLabels = ["Insig", "Minor", "Mod", "Major", "Severe"]; + const xAxisLabels = ["Insignificant", "Minor", "Moderate", "Major", "Severe"]; // Store the active cell position values const activeProbability = vendor.inherentProbability; @@ -119,121 +125,86 @@ export function InherentRiskVendorChart({ vendor }: InherentRiskChartProps) { -
- {/* 5x5 Risk Matrix */} -
- {/* Y-axis label */} -
+
+ {/* Y-axis Title - Hidden on small/medium screens */} +
+ Probability -
- - {/* Main grid container */} -
-
- {/* Grid rows */} - {[...Array(5)].map((_, rowIndex) => { - // Map row index to likelihood enum based on visual order - const rowLikelihood = VISUAL_LIKELIHOOD_ORDER[rowIndex]; - - return ( -
- {/* Grid cells for this row */} - {[...Array(5)].map((_, colIndex) => { - // Map column index to impact enum - const colImpact = Object.keys(IMPACT_SCORES)[ - colIndex - ] as Impact; - - // Calculate cell score and color - const likelihoodScore = - LIKELIHOOD_SCORES[rowLikelihood]; - const impactScore = IMPACT_SCORES[colImpact]; - const cellScore = likelihoodScore * impactScore; - - let cellColor = RISK_COLORS.low; - if (cellScore > 16) cellColor = RISK_COLORS.critical; - else if (cellScore > 9) cellColor = RISK_COLORS.high; - else if (cellScore > 4) - cellColor = RISK_COLORS.medium; - - // Check if this is the active cell - const isActive = - rowLikelihood === activeProbability && - colImpact === activeImpact; - - return ( -
- {isActive && ( -
-
-
- )} -
- ); - })} -
- ); - })} - - {/* Y-axis labels - positioned outside the grid */} - {yAxisLabels.map((label, i) => ( -
- {label} -
- ))} + +
+ + {/* Y-axis Labels Area - Hidden on small/medium screens */} +
+ {yAxisLabels.map((label, i) => ( +
+ {label} +
+ ))} +
- {/* X-axis labels */} - {xAxisLabels.map((label, i) => ( + {/* 5x5 Matrix Grid - Spans full area on small/medium screens */} +
+ {VISUAL_LIKELIHOOD_ORDER.map((rowLikelihood, rowIndex) => + VISUAL_IMPACT_ORDER.map((colImpact, colIndex) => { + const likelihoodScore = LIKELIHOOD_SCORES[rowLikelihood]; + const impactScore = IMPACT_SCORES[colImpact]; + const cellScore = likelihoodScore * impactScore; + + let cellColor = RISK_COLORS.low; + if (cellScore > 16) cellColor = RISK_COLORS.critical; + else if (cellScore > 9) cellColor = RISK_COLORS.high; + else if (cellScore > 4) cellColor = RISK_COLORS.medium; + + const isActive = + rowLikelihood === activeProbability && + colImpact === activeImpact; + + return (
- {label} + {isActive && ( +
+ )}
- ))} - - {/* X-axis title */} -
- Impact -
+ ); + }), + )} +
+ + {/* X-axis Labels Area - Hidden on small/medium screens */} +
+ {xAxisLabels.map((label, i) => ( +
+ {label}
-
+ ))} +
+ + {/* X-axis Title - Hidden on small/medium screens */} +
+ + Impact +
diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk-vendor-chart.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk-vendor-chart.tsx index 62d22920fc..dd40e0800e 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk-vendor-chart.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk-vendor-chart.tsx @@ -62,7 +62,7 @@ export function ResidualRiskVendorChart({ vendor }: ResidualRiskChartProps) { // Get color based on risk level const riskColor = RISK_COLORS[riskLevel as keyof typeof RISK_COLORS]; - // Define the visual order of likelihood for rendering + // Define the visual order for rows and columns const VISUAL_LIKELIHOOD_ORDER: Likelihood[] = [ Likelihood.very_likely, Likelihood.likely, @@ -70,16 +70,22 @@ export function ResidualRiskVendorChart({ vendor }: ResidualRiskChartProps) { Likelihood.unlikely, Likelihood.very_unlikely, ]; + const VISUAL_IMPACT_ORDER: Impact[] = [ + Impact.insignificant, + Impact.minor, + Impact.moderate, + Impact.major, + Impact.severe, + ]; - // We'll determine the active cell while building the grid const yAxisLabels = [ - "V.Likely", // Corresponds to VISUAL_LIKELIHOOD_ORDER[0] + "Very Likely", // Corresponds to VISUAL_LIKELIHOOD_ORDER[0] "Likely", "Possible", "Unlikely", - "V.Unlikely", // Corresponds to VISUAL_LIKELIHOOD_ORDER[4] + "Very Unlikely", // Corresponds to VISUAL_LIKELIHOOD_ORDER[4] ]; - const xAxisLabels = ["Insig", "Minor", "Mod", "Major", "Severe"]; + const xAxisLabels = ["Insignificant", "Minor", "Moderate", "Major", "Severe"]; // Store the active cell position values const activeProbability = vendor.residualProbability; @@ -111,121 +117,86 @@ export function ResidualRiskVendorChart({ vendor }: ResidualRiskChartProps) {
-
- {/* 5x5 Risk Matrix */} -
- {/* Y-axis label */} -
+
+ {/* Y-axis Title - Hidden on small/medium screens */} +
+ Probability -
- - {/* Main grid container */} -
-
- {/* Grid rows */} - {[...Array(5)].map((_, rowIndex) => { - // Map row index to likelihood enum based on visual order - const rowLikelihood = VISUAL_LIKELIHOOD_ORDER[rowIndex]; - - return ( -
- {/* Grid cells for this row */} - {[...Array(5)].map((_, colIndex) => { - // Map column index to impact enum - const colImpact = Object.keys(IMPACT_SCORES)[ - colIndex - ] as Impact; - - // Calculate cell score and color - const likelihoodScore = - LIKELIHOOD_SCORES[rowLikelihood]; - const impactScore = IMPACT_SCORES[colImpact]; - const cellScore = likelihoodScore * impactScore; - - let cellColor = RISK_COLORS.low; - if (cellScore > 16) cellColor = RISK_COLORS.critical; - else if (cellScore > 9) cellColor = RISK_COLORS.high; - else if (cellScore > 4) - cellColor = RISK_COLORS.medium; - - // Check if this is the active cell - const isActive = - rowLikelihood === activeProbability && - colImpact === activeImpact; - - return ( -
- {isActive && ( -
-
-
- )} -
- ); - })} -
- ); - })} - - {/* Y-axis labels - positioned outside the grid */} - {yAxisLabels.map((label, i) => ( -
- {label} -
- ))} + +
+ + {/* Y-axis Labels Area - Hidden on small/medium screens */} +
+ {yAxisLabels.map((label, i) => ( +
+ {label} +
+ ))} +
- {/* X-axis labels */} - {xAxisLabels.map((label, i) => ( + {/* 5x5 Matrix Grid - Spans full area on small/medium screens */} +
+ {VISUAL_LIKELIHOOD_ORDER.map((rowLikelihood, rowIndex) => + VISUAL_IMPACT_ORDER.map((colImpact, colIndex) => { + const likelihoodScore = LIKELIHOOD_SCORES[rowLikelihood]; + const impactScore = IMPACT_SCORES[colImpact]; + const cellScore = likelihoodScore * impactScore; + + let cellColor = RISK_COLORS.low; + if (cellScore > 16) cellColor = RISK_COLORS.critical; + else if (cellScore > 9) cellColor = RISK_COLORS.high; + else if (cellScore > 4) cellColor = RISK_COLORS.medium; + + const isActive = + rowLikelihood === activeProbability && + colImpact === activeImpact; + + return (
- {label} + {isActive && ( +
+ )}
- ))} - - {/* X-axis title */} -
- Impact -
+ ); + }), + )} +
+ + {/* X-axis Labels Area - Hidden on small/medium screens */} +
+ {xAxisLabels.map((label, i) => ( +
+ {label}
-
+ ))} +
+ + {/* X-axis Title - Hidden on small/medium screens */} +
+ + Impact +
From c4ed4f5ec27873421c1b1e58809114b20ab6900a Mon Sep 17 00:00:00 2001 From: Mariano Fuentes Date: Thu, 3 Apr 2025 19:27:08 -0400 Subject: [PATCH 2/2] refactor: streamline risk forms and charts for improved clarity and performance - Removed unnecessary console logs from InherentRiskVendorChart and ResidualRiskVendorChart for cleaner output. - Simplified state management in InherentRiskSheet and ResidualRiskSheet by directly using query state. - Enhanced form submission logic in InherentRiskForm and ResidualRiskForm to improve user experience and state handling. - Updated component structure for better readability and maintainability. --- .../components/inherent-risk-vendor-chart.tsx | 11 ---- .../[vendorId]/components/inherent-risk.tsx | 20 ++----- .../components/residual-risk-vendor-chart.tsx | 5 +- .../[vendorId]/components/residual-risk.tsx | 55 ++----------------- .../forms/risks/inherent-risk-form.tsx | 40 ++------------ .../forms/risks/residual-risk-form.tsx | 37 ++----------- 6 files changed, 19 insertions(+), 149 deletions(-) diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk-vendor-chart.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk-vendor-chart.tsx index 92bad86193..e7127621bd 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk-vendor-chart.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk-vendor-chart.tsx @@ -48,14 +48,6 @@ export function InherentRiskVendorChart({ vendor }: InherentRiskChartProps) { const t = useI18n(); const [open, setOpen] = useQueryState("inherent-risk-sheet"); - // Debug information - console.log("VENDOR DATA:", { - inherentProbability: vendor.inherentProbability, - inherentImpact: vendor.inherentImpact, - probabilityScore: LIKELIHOOD_SCORES[vendor.inherentProbability], - impactScore: IMPACT_SCORES[vendor.inherentImpact], - }); - // Calculate risk score from probability and impact const riskScore = LIKELIHOOD_SCORES[vendor.inherentProbability] * @@ -67,9 +59,6 @@ export function InherentRiskVendorChart({ vendor }: InherentRiskChartProps) { else if (riskScore > 9) riskLevel = "high"; else if (riskScore > 4) riskLevel = "medium"; - // Get color based on risk level - const riskColor = RISK_COLORS[riskLevel as keyof typeof RISK_COLORS]; - // Define the visual order for rows and columns const VISUAL_LIKELIHOOD_ORDER: Likelihood[] = [ Likelihood.very_likely, diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk.tsx index b7a7e91287..07590325ad 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/inherent-risk.tsx @@ -21,29 +21,19 @@ export function InherentRiskSheet({ vendorId, initialProbability, initialImpact, - onSuccess, }: { vendorId: string; initialProbability?: Likelihood; initialImpact?: Impact; - onSuccess?: () => void; }) { const t = useI18n(); const isDesktop = useMediaQuery("(min-width: 768px)"); - const [open, setOpen] = useQueryState("inherent-risk-sheet"); - const isOpen = open === "true"; - - const handleClose = () => setOpen(null); - - const handleFormSuccess = () => { - setOpen(null); - if (onSuccess) onSuccess(); - }; + const [isOpen, setOpen] = useQueryState("inherent-risk-sheet"); if (isDesktop) { return ( setOpen(value ? "true" : null)} > @@ -54,7 +44,7 @@ export function InherentRiskSheet({ size="icon" variant="ghost" className="p-0 m-0 size-auto hover:bg-transparent" - onClick={handleClose} + onClick={() => setOpen(null)} > @@ -69,7 +59,6 @@ export function InherentRiskSheet({ vendorId={vendorId} initialProbability={initialProbability} initialImpact={initialImpact} - onSuccess={handleFormSuccess} /> @@ -79,7 +68,7 @@ export function InherentRiskSheet({ return ( setOpen(value ? "true" : null)} > diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk-vendor-chart.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk-vendor-chart.tsx index dd40e0800e..fc2ec20f18 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk-vendor-chart.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk-vendor-chart.tsx @@ -46,7 +46,7 @@ const RISK_COLORS = { export function ResidualRiskVendorChart({ vendor }: ResidualRiskChartProps) { const t = useI18n(); - const [open, setOpen] = useQueryState("residual-risk-sheet"); + const [, setOpen] = useQueryState("residual-risk-sheet"); // Calculate risk score from probability and impact const riskScore = @@ -59,9 +59,6 @@ export function ResidualRiskVendorChart({ vendor }: ResidualRiskChartProps) { else if (riskScore > 9) riskLevel = "high"; else if (riskScore > 4) riskLevel = "medium"; - // Get color based on risk level - const riskColor = RISK_COLORS[riskLevel as keyof typeof RISK_COLORS]; - // Define the visual order for rows and columns const VISUAL_LIKELIHOOD_ORDER: Likelihood[] = [ Likelihood.very_likely, diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk.tsx index 4fe6157dbc..9d55fecfb6 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/components/residual-risk.tsx @@ -16,62 +16,22 @@ import { X } from "lucide-react"; import { ResidualRiskForm } from "@/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/forms/risks/residual-risk-form"; import type { Vendor } from "@comp/db/types"; import { useQueryState } from "nuqs"; -import { useRouter, useSearchParams } from "next/navigation"; export function ResidualRiskSheet({ vendorId, initialRisk, - onSuccess, }: { vendorId: string; initialRisk?: Vendor; - onSuccess?: () => void; }) { const t = useI18n(); - const router = useRouter(); - const searchParams = useSearchParams(); const isDesktop = useMediaQuery("(min-width: 768px)"); - const [open, setOpen] = useQueryState("residual-risk-sheet"); - const isOpen = open === "true"; - - const handleClose = () => { - setOpen(null); - - // Create new URLSearchParams without the residual-risk-sheet parameter - const params = new URLSearchParams(searchParams); - params.delete("residual-risk-sheet"); - - // Create the new URL path with the updated query parameters - const newPath = - window.location.pathname + - (params.toString() ? `?${params.toString()}` : ""); - - // Update the URL without refreshing the page - router.replace(newPath); - }; - - const handleFormSuccess = () => { - setOpen(null); - - // Remove query params on success - const params = new URLSearchParams(searchParams); - params.delete("residual-risk-sheet"); - - const newPath = - window.location.pathname + - (params.toString() ? `?${params.toString()}` : ""); - - router.replace(newPath); - - if (onSuccess) onSuccess(); - }; + const [isOpen, setOpen] = useQueryState("residual-risk-sheet"); + const open = isOpen === "true"; if (isDesktop) { return ( - (value ? setOpen("true") : handleClose())} - > +
@@ -80,7 +40,7 @@ export function ResidualRiskSheet({ size="icon" variant="ghost" className="p-0 m-0 size-auto hover:bg-transparent" - onClick={handleClose} + onClick={() => setOpen("false")} > @@ -95,7 +55,6 @@ export function ResidualRiskSheet({ vendorId={vendorId} initialProbability={initialRisk?.residualProbability} initialImpact={initialRisk?.residualImpact} - onSuccess={handleFormSuccess} /> @@ -104,10 +63,7 @@ export function ResidualRiskSheet({ } return ( - (value ? setOpen("true") : handleClose())} - > + @@ -116,7 +72,6 @@ export function ResidualRiskSheet({ vendorId={vendorId} initialProbability={initialRisk?.residualProbability} initialImpact={initialRisk?.residualImpact} - onSuccess={handleFormSuccess} /> diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/forms/risks/inherent-risk-form.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/forms/risks/inherent-risk-form.tsx index ac093b73d7..4c701dc9e2 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/forms/risks/inherent-risk-form.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/forms/risks/inherent-risk-form.tsx @@ -1,5 +1,6 @@ "use client"; +import { updateVendorInherentRisk } from "@/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/update-vendor-inherent-risk"; import { useI18n } from "@/locales/client"; import { Button } from "@comp/ui/button"; import { @@ -19,13 +20,10 @@ import { } from "@comp/ui/select"; import { useToast } from "@comp/ui/use-toast"; import { zodResolver } from "@hookform/resolvers/zod"; -import { useRouter, useSearchParams } from "next/navigation"; -import { useForm } from "react-hook-form"; -import { z } from "zod"; -import { updateVendorInherentRisk } from "@/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/update-vendor-inherent-risk"; -import type { ActionResponse } from "@/types/actions"; import { Impact, Likelihood } from "@prisma/client"; import { useQueryState } from "nuqs"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; const formSchema = z.object({ inherentProbability: z.nativeEnum(Likelihood), @@ -38,19 +36,15 @@ interface InherentRiskFormProps { vendorId: string; initialProbability?: Likelihood; initialImpact?: Impact; - onSuccess?: () => void; } export function InherentRiskForm({ vendorId, initialProbability = Likelihood.very_unlikely, initialImpact = Impact.insignificant, - onSuccess, }: InherentRiskFormProps) { const t = useI18n(); const { toast } = useToast(); - const router = useRouter(); - const searchParams = useSearchParams(); const [_, setOpen] = useQueryState("inherent-risk-sheet"); const form = useForm({ @@ -63,42 +57,18 @@ export function InherentRiskForm({ async function onSubmit(values: FormValues) { try { - // Call the server action - const response = await updateVendorInherentRisk({ + await updateVendorInherentRisk({ vendorId, inherentProbability: values.inherentProbability, inherentImpact: values.inherentImpact, }); - const result = response as unknown as ActionResponse; - - if (!result?.success) { - toast({ - title: t("common.error"), - description: result?.error || t("common.unexpected_error"), - variant: "destructive", - }); - return; // Stop execution on failure - } - - // On success: - // 1. Show success toast toast({ title: t("common.success"), description: t("vendors.risks.inherent_risk_updated"), }); - // 2. Refresh the page data first to ensure it's updated before navigation - router.refresh(); - - // 3. Close the sheet by navigating to the same route without the query parameter - const params = new URLSearchParams(searchParams); - params.delete("inherent-risk-sheet"); - const newPath = `${window.location.pathname}${params.size > 0 ? `?${params.toString()}` : ""}`; - router.replace(newPath, { scroll: false }); - - // 4. Call onSuccess callback if provided (optional, might not be needed if navigation handles updates) - if (onSuccess) onSuccess(); + setOpen("false"); } catch (error) { console.error("Error submitting form:", error); toast({ diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/forms/risks/residual-risk-form.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/forms/risks/residual-risk-form.tsx index 34348c68c9..461b5378ce 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/forms/risks/residual-risk-form.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/forms/risks/residual-risk-form.tsx @@ -1,5 +1,6 @@ "use client"; +import { updateVendorResidualRisk } from "@/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/update-vendor-residual-risk"; import { useI18n } from "@/locales/client"; import { Button } from "@comp/ui/button"; import { @@ -19,13 +20,10 @@ import { } from "@comp/ui/select"; import { useToast } from "@comp/ui/use-toast"; import { zodResolver } from "@hookform/resolvers/zod"; -import { useRouter, useSearchParams } from "next/navigation"; -import { useForm } from "react-hook-form"; -import { z } from "zod"; -import { updateVendorResidualRisk } from "@/app/[locale]/(app)/(dashboard)/[orgId]/vendors/[vendorId]/actions/update-vendor-residual-risk"; -import type { ActionResponse } from "@/types/actions"; import { Impact, Likelihood } from "@prisma/client"; import { useQueryState } from "nuqs"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; const formSchema = z.object({ residualProbability: z.nativeEnum(Likelihood), @@ -38,19 +36,15 @@ interface ResidualRiskFormProps { vendorId: string; initialProbability?: Likelihood; initialImpact?: Impact; - onSuccess?: () => void; } export function ResidualRiskForm({ vendorId, initialProbability = Likelihood.very_unlikely, initialImpact = Impact.insignificant, - onSuccess, }: ResidualRiskFormProps) { const t = useI18n(); const { toast } = useToast(); - const router = useRouter(); - const searchParams = useSearchParams(); const [_, setOpen] = useQueryState("residual-risk-sheet"); const form = useForm({ @@ -70,35 +64,12 @@ export function ResidualRiskForm({ residualImpact: values.residualImpact, }); - const result = response as unknown as ActionResponse; - - if (!result?.success) { - toast({ - title: t("common.error"), - description: result?.error || t("common.unexpected_error"), - variant: "destructive", - }); - return; // Stop execution on failure - } - - // On success: - // 1. Show success toast toast({ title: t("common.success"), description: t("vendors.risks.residual_risk_updated"), }); - // 2. Refresh the page data first to ensure it's updated before navigation - router.refresh(); - - // 3. Close the sheet by navigating to the same route without the query parameter - const params = new URLSearchParams(searchParams); - params.delete("residual-risk-sheet"); - const newPath = `${window.location.pathname}${params.size > 0 ? `?${params.toString()}` : ""}`; - router.replace(newPath, { scroll: false }); - - // 4. Call onSuccess callback if provided (optional, might not be needed if navigation handles updates) - if (onSuccess) onSuccess(); + setOpen("false"); } catch (error) { console.error("Error submitting form:", error); toast({