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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 5x 9x 9x 9x 1x 8x 9x 9x 1x 1x | import React from 'react';
import {
Box,
Typography,
Alert,
FormControlLabel,
Switch,
Button,
Divider,
Stack,
} from '@mui/material';
import { Block as BlockIcon } from '@mui/icons-material';
import { useTranslation } from 'react-i18next';
interface User {
username: string;
role: 'ORGANIZER' | 'PARTNER' | 'SPEAKER' | 'ATTENDEE';
}
interface PartnerDetail {
companyName: string; // ADR-003: companyName is the meaningful ID
partnershipLevel: 'STRATEGIC' | 'PLATINUM' | 'GOLD' | 'SILVER' | 'BRONZE';
partnershipStartDate: string;
isActive?: boolean;
autoRenewal?: boolean;
renewalDate?: string;
}
interface PartnerSettingsTabProps {
partner: PartnerDetail;
currentUser: User;
onUpdateStatus?: (active: boolean) => void;
onUpdateAutoRenewal?: (autoRenewal: boolean) => void;
}
/**
* PartnerSettingsTab Component
* Organizer-only settings tab for partner configuration
*/
export const PartnerSettingsTab: React.FC<PartnerSettingsTabProps> = ({
partner,
currentUser,
onUpdateStatus,
onUpdateAutoRenewal,
}) => {
const { t } = useTranslation('partners');
const isOrganizer = currentUser.role === 'ORGANIZER';
if (!isOrganizer) {
return (
<Box sx={{ p: 3 }}>
<Alert severity="error" icon={<BlockIcon />}>
<Typography variant="h6">{t('detail.settingsTab.accessDenied')}</Typography>
<Typography variant="body2">{t('detail.settingsTab.accessDeniedMessage')}</Typography>
</Alert>
</Box>
);
}
const renewalDateFormatted = partner.renewalDate
? new Date(partner.renewalDate).toLocaleDateString('en', {
year: 'numeric',
month: 'short',
day: 'numeric',
})
: null;
const epicDeferredTitle = 'Epic 8 feature — not yet implemented';
return (
<Box sx={{ p: 3 }}>
<Typography variant="h5" gutterBottom>
{t('detail.settingsTab.title', 'Settings')}
</Typography>
<Stack spacing={3} sx={{ mt: 2 }}>
<Box>
<Typography variant="h6" gutterBottom>
{t('detail.settingsTab.activePartnership', 'Active Partnership')}
</Typography>
<FormControlLabel
control={
<Switch
checked={partner.isActive ?? false}
onChange={(e) => onUpdateStatus?.(e.target.checked)}
/>
}
label={t('common:filters.status.active')}
/>
</Box>
<Divider />
<Box>
<Typography variant="h6" gutterBottom>
{t('detail.settingsTab.autoRenewal', 'Auto-Renewal')}
</Typography>
<FormControlLabel
control={
<Switch
checked={partner.autoRenewal ?? false}
onChange={(e) => onUpdateAutoRenewal?.(e.target.checked)}
/>
}
label={t('detail.settingsTab.autoRenewal')}
/>
{renewalDateFormatted && (
<Typography variant="body2" sx={{ mt: 1 }}>
{t('detail.settingsTab.renewalDate', 'Renewal Date')}: {renewalDateFormatted}
</Typography>
)}
</Box>
<Divider />
<Stack direction="row" spacing={2}>
<Button variant="outlined" disabled title={epicDeferredTitle}>
{t('detail.settingsTab.exportData', 'Export')}
</Button>
<Button variant="outlined" color="error" disabled title={epicDeferredTitle}>
{t('detail.settingsTab.deletePartner', 'Delete')}
</Button>
</Stack>
</Stack>
</Box>
);
};
|