admin/context/AlertModalContext.tsx
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

139 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import { AlertDialog } from '@heroui/react'
import React, { createContext, useState } from 'react'
import type { AlertModalContextType, ShowAlertOptions } from '@/types'
import ConsumerModal from '@/components/consumer/ConsumerModal'
import Button from '@/components/formElements/Button'
import { useMediaQuery } from '@/hooks/useMediaQuery'
import { cn } from '@/lib/cn'
export const AlertModalContext = createContext<AlertModalContextType | undefined>(undefined)
interface AlertModalProviderProps {
children: React.ReactNode
variant?: 'default' | 'consumer'
}
export const AlertModalProvider = ({ children, variant = 'default' }: AlertModalProviderProps) => {
const isMobile = useMediaQuery('(max-width: 768px)')
const [isVisible, setIsVisible] = useState(false)
const [isConfirming, setIsConfirming] = useState(false)
const [message, setMessage] = useState('')
const [onConfirm, setOnConfirm] = useState<((data?: unknown) => unknown) | undefined>(undefined)
const [confirmData, setConfirmData] = useState<unknown>(undefined)
const [dangerAccept, setDangerAccept] = useState(false)
const showAlert = (msg: string, confirmCallback?: (data?: unknown) => unknown, data?: unknown, options?: ShowAlertOptions) => {
setMessage(msg)
setOnConfirm(() => confirmCallback)
setConfirmData(data)
setDangerAccept(Boolean(options?.dangerAccept))
setIsVisible(true)
}
const hideAlert = () => {
if (isConfirming) return
setIsVisible(false)
setMessage('')
setOnConfirm(undefined)
setConfirmData(undefined)
setDangerAccept(false)
}
const confirmAlert = async () => {
setIsConfirming(true)
try {
if (onConfirm) await onConfirm(confirmData)
} finally {
setIsConfirming(false)
setIsVisible(false)
setMessage('')
setOnConfirm(undefined)
setConfirmData(undefined)
setDangerAccept(false)
}
}
return (
<AlertModalContext.Provider value={{ showAlert, hideAlert }}>
{children}
{variant === 'consumer' ? (
<ConsumerModal
cancelLabel="انصراف"
isDismissable={false}
isOpen={isVisible}
isSubmitting={isConfirming}
stackLevel={1}
submitLabel="تأیید"
title="تأیید"
onCancel={hideAlert}
onOpenChange={(isOpen) => {
if (!isOpen) hideAlert()
}}
onSubmit={confirmAlert}
>
<p className="text-center font-semibold leading-7 text-overlay-foreground">{message}</p>
</ConsumerModal>
) : (
<AlertDialog>
<AlertDialog.Backdrop
isKeyboardDismissDisabled
className="z-[60]"
isDismissable={false}
isOpen={isVisible}
onOpenChange={(isOpen) => {
if (!isOpen) hideAlert()
}}
>
<AlertDialog.Container
className={isMobile ? 'p-0' : undefined}
placement={isMobile ? 'bottom' : 'center'}
size="xs"
>
<AlertDialog.Dialog
className={cn(
'border border-border bg-overlay text-right shadow-overlay sm:max-w-[400px]',
isMobile &&
'mx-0 mt-auto w-full max-w-none rounded-b-none rounded-t-3xl border-b-0 pb-[max(1rem,env(safe-area-inset-bottom))]'
)}
>
<AlertDialog.Header className="items-center text-center">
<AlertDialog.Icon status={dangerAccept ? 'danger' : 'warning'} />
</AlertDialog.Header>
<AlertDialog.Body className="text-center font-semibold leading-7 text-overlay-foreground">
<p>{message}</p>
</AlertDialog.Body>
<AlertDialog.Footer className="grid grid-cols-2 gap-2">
<Button
fullWidth
color="default"
disabled={isConfirming}
variant="light"
onClick={hideAlert}
>
انصراف
</Button>
<Button
fullWidth
color={dangerAccept ? 'danger' : 'primary'}
disabled={isConfirming}
isLoading={isConfirming}
variant={dangerAccept ? 'flat' : 'solid'}
onClick={confirmAlert}
>
تأیید
</Button>
</AlertDialog.Footer>
</AlertDialog.Dialog>
</AlertDialog.Container>
</AlertDialog.Backdrop>
</AlertDialog>
)}
</AlertModalContext.Provider>
)
}