All files / src/components/organizer/NewsletterSubscribers DeleteSubscriberDialog.tsx

80% Statements 12/15
62.5% Branches 5/8
75% Functions 3/4
84.61% Lines 11/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101                                                                        2x           7x 7x 7x 7x   7x 7x     7x 1x 1x               7x                                                                              
/**
 * DeleteSubscriberDialog — Destructive confirmation dialog
 *
 * Mirrors DeleteUserDialog.tsx pattern.
 *
 * Story 10.28: Newsletter Subscriber Management Page
 */
 
import React from 'react';
import {
  Alert,
  Box,
  Button,
  CircularProgress,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  IconButton,
  Typography,
} from '@mui/material';
import { Close, ErrorOutline } from '@mui/icons-material';
import { useTranslation } from 'react-i18next';
import type { components } from '@/types/generated/event-newsletter-api.types';
import { useBreakpoints } from '@/hooks/useBreakpoints';
import { useDeleteSubscriber } from '@/hooks/useNewsletterSubscribers';
 
type SubscriberResponse = components['schemas']['SubscriberResponse'];
 
interface DeleteSubscriberDialogProps {
  open: boolean;
  subscriber: SubscriberResponse | null;
  onClose: () => void;
  onSuccess: () => void;
}
 
const DeleteSubscriberDialog: React.FC<DeleteSubscriberDialogProps> = ({
  open,
  subscriber,
  onClose,
  onSuccess,
}) => {
  const { t } = useTranslation('newsletterSubscribers');
  const { t: tCommon } = useTranslation('common');
  const { isMobile } = useBreakpoints();
  const mutation = useDeleteSubscriber();
 
  React.useEffect(() => {
    if (open) mutation.reset();
  }, [open, mutation]);
 
  const handleConfirm = () => {
    Iif (!subscriber?.id) return;
    mutation.mutate(subscriber.id, {
      onSuccess: () => {
        onSuccess();
        onClose();
      },
    });
  };
 
  return (
    <Dialog open={open} onClose={onClose} maxWidth="sm" fullWidth fullScreen={isMobile}>
      <DialogTitle>
        <Box display="flex" justifyContent="space-between" alignItems="center">
          <Box display="flex" alignItems="center" gap={1}>
            <ErrorOutline color="error" />
            <Typography variant="h6">{t('dialogs.delete.title')}</Typography>
          </Box>
          <IconButton onClick={onClose} aria-label={tCommon('actions.close')}>
            <Close />
          </IconButton>
        </Box>
      </DialogTitle>
      <DialogContent dividers>
        <Typography>{t('dialogs.delete.message', { email: subscriber?.email })}</Typography>
        {mutation.isError && (
          <Alert severity="error" sx={{ mt: 2 }}>
            {tCommon('errors.unexpected')}
          </Alert>
        )}
      </DialogContent>
      <DialogActions>
        <Button onClick={onClose} variant="outlined">
          {tCommon('actions.cancel')}
        </Button>
        <Button
          onClick={handleConfirm}
          variant="contained"
          color="error"
          disabled={mutation.isPending}
        >
          {mutation.isPending ? <CircularProgress size={20} /> : t('actions.delete')}
        </Button>
      </DialogActions>
    </Dialog>
  );
};
 
export default DeleteSubscriberDialog;