Files
lti-web-client/src/components/modal/ConfirmationModal.tsx
T

215 lines
5.6 KiB
TypeScript

'use client';
import { MouseEventHandler, RefObject, useState } from 'react';
import { Icon } from '@iconify/react';
import Modal from '@/components/Modal';
import Button, { ButtonProps } from '@/components/Button';
import { cn } from '@/lib/helper';
export type IconPosition = 'left' | 'center' | 'right';
export interface ConfirmationModalProps {
ref: RefObject<HTMLDialogElement | null>;
type?: 'info' | 'success' | 'error';
text?: string;
subtitleText?: string;
closeOnBackdrop?: boolean;
primaryButton?: ButtonProps & {
text?: string;
};
secondaryButton?: ButtonProps & {
text?: string;
};
className?: {
modal?: string;
modalBox?: string;
};
children?: React.ReactNode;
iconSize?: number;
iconPosition?: IconPosition;
}
const iconConfig = {
info: {
icon: 'material-symbols:info-outline-rounded',
iconClassName: 'text-info-content',
bgClassName: 'bg-info',
outerRingClassName: 'bg-info/20',
borderClassName: 'border-info',
},
success: {
icon: 'heroicons:check',
iconClassName: 'text-white',
bgClassName: 'bg-[#00D390]',
outerRingClassName: 'bg-[#00D3901F]',
borderClassName: 'border-[#CCF7EB]',
},
error: {
icon: 'solar:danger-triangle-linear',
iconClassName: 'text-error-content',
bgClassName: 'bg-[#f03338]',
outerRingClassName: 'bg-[#f3cdcd]',
borderClassName: 'border-[#fff0ef]',
},
} as const;
const ConfirmationModalIcon = ({
type,
size = 24,
}: {
type: 'info' | 'success' | 'error';
size?: number;
}) => {
const config = iconConfig[type];
return (
<div className='flex items-center justify-center p-2'>
<div
className={cn(
'rounded-full border-4 p-1',
config.outerRingClassName,
config.borderClassName
)}
>
<div className={cn('rounded-full p-1', config.outerRingClassName)}>
<div
className={cn(
'rounded-full p-3 flex items-center justify-center',
config.bgClassName
)}
>
<Icon
icon={config.icon}
width={size}
height={size}
className={config.iconClassName}
/>
</div>
</div>
</div>
</div>
);
};
const ConfirmationModal = ({
ref,
type = 'info',
text,
subtitleText,
closeOnBackdrop,
primaryButton,
secondaryButton,
className,
children,
iconSize = 32,
iconPosition = 'center',
}: ConfirmationModalProps) => {
const [isPrimaryButtonLoading, setIsPrimaryButtonLoading] = useState(false);
const closeModalHandler = () => {
ref.current?.close();
};
const primaryButtonClickHandler: MouseEventHandler<
HTMLButtonElement
> = async (event) => {
setIsPrimaryButtonLoading(true);
await primaryButton?.onClick?.(event);
setIsPrimaryButtonLoading(false);
};
return (
<Modal ref={ref} closeOnBackdrop={closeOnBackdrop} className={className}>
<div className='w-full flex flex-col gap-4'>
{iconPosition === 'center' ? (
<>
<div className='w-fit mx-auto'>
<ConfirmationModalIcon type={type} size={iconSize} />
</div>
<p className='text-center font-medium'>
{text ?? 'Apakah anda yakin ingin melakukan hal ini?'}
</p>
{subtitleText && (
<p className='text-center text-sm text-gray-400'>
{subtitleText}
</p>
)}
</>
) : (
<div
className={cn('flex flex-row items-center gap-4', {
'flex-row': iconPosition === 'left',
'flex-row-reverse': iconPosition === 'right',
})}
>
<div className='w-fit'>
<ConfirmationModalIcon type={type} size={iconSize} />
</div>
<div className='flex flex-col gap-1'>
<p className='font-medium'>
{text ?? 'Apakah anda yakin ingin melakukan hal ini?'}
</p>
{subtitleText && (
<p className='text-sm text-gray-400'>{subtitleText}</p>
)}
</div>
</div>
)}
{children && <div className='w-full'>{children}</div>}
<div className='w-full flex flex-row gap-2'>
{secondaryButton && secondaryButton.text && (
<Button
{...secondaryButton}
variant='outline'
color={secondaryButton?.color}
isLoading={secondaryButton?.isLoading}
disabled={
secondaryButton?.isLoading !== undefined
? secondaryButton?.isLoading
: isPrimaryButtonLoading
}
onClick={closeModalHandler}
className='grow'
>
{secondaryButton?.text ?? 'Tidak'}
</Button>
)}
{primaryButton && primaryButton.text && (
<Button
{...primaryButton}
color={primaryButton?.color ?? 'info'}
onClick={primaryButtonClickHandler}
isLoading={
primaryButton?.isLoading !== undefined
? primaryButton?.isLoading
: isPrimaryButtonLoading
}
disabled={
primaryButton?.isLoading !== undefined
? primaryButton?.isLoading
: isPrimaryButtonLoading
}
className='grow'
>
{primaryButton?.text ?? 'Ya'}
</Button>
)}
</div>
</div>
</Modal>
);
};
export default ConfirmationModal;