Enhance handling of associated pgroups in Contacts and Address views.

Ensure `associatedPgroups` defaults to an empty array to avoid undefined behavior. Add non-editable pgroups input fields for new items and improve conditional rendering of pgroup chips in both views. Minor structural updates for consistency and clarity.
This commit is contained in:
GotthardG 2025-01-22 16:44:03 +01:00
parent 382b1eaba8
commit 4a1852882a
2 changed files with 62 additions and 49 deletions

View File

@ -49,6 +49,7 @@ const AddressManager: React.FC<AddressManagerProps> = ({ pgroups, activePgroup }
const [countrySuggestions, setCountrySuggestions] = React.useState<string[]>([]);
const [addresses, setAddresses] = React.useState<Address[]>([]);
const [newAddress, setNewAddress] = React.useState<Partial<Address>>({
pgroups: activePgroup,
house_number: '',
street: '',
city: '',
@ -80,13 +81,13 @@ const AddressManager: React.FC<AddressManagerProps> = ({ pgroups, activePgroup }
try {
const response = await AddressesService.getAllAddressesProtectedAddressesAllGet();
// Preprocess: Add associated and unassociated pgroups
// Preprocess: Add associated pgroups with a default value if not available
const transformedAddresses = response.map((address) => {
const addressPgroups = address.pgroups?.split(',').map((p) => p.trim()) || [];
const associatedPgroups = pgroups.filter((pgroup) => addressPgroups.includes(pgroup));
return {
...address,
associatedPgroups, // pgroups linked to the address
associatedPgroups: associatedPgroups || [], // Ensure it's always an array
};
});
@ -240,7 +241,7 @@ const AddressManager: React.FC<AddressManagerProps> = ({ pgroups, activePgroup }
<TextField
label="pgroup"
name="pgroup"
value={newAddress.activePgroup || ''}
value={newAddress.pgroups || ''}
disabled
sx={{ width: '120px' }} // Small fixed-size for non-editable field
/>
@ -343,7 +344,9 @@ const AddressManager: React.FC<AddressManagerProps> = ({ pgroups, activePgroup }
primary={`${address.house_number}, ${address.street}, ${address.city}`}
secondary={
<Box display="flex" flexWrap="wrap">
{renderPgroupChips(address)}
{address.associatedPgroups
? renderPgroupChips(address) // Render chips if associatedPgroups is available
: null}
</Box>
}
/>

View File

@ -37,6 +37,7 @@ interface ContactWithPgroups extends Contact {
const ContactsManager: React.FC<ContactsManagerProps> = ({ pgroups, activePgroup }) => {
const [contacts, setContacts] = React.useState<ContactWithPgroups[]>([]);
const [newContact, setNewContact] = React.useState<Partial<Contact>>({
pgroups: activePgroup,
firstname: '',
lastname: '',
phone_number: '',
@ -58,7 +59,7 @@ const ContactsManager: React.FC<ContactsManagerProps> = ({ pgroups, activePgroup
const associatedPgroups = pgroups.filter((pgroup) => contactPgroups.includes(pgroup));
return {
...contact,
associatedPgroups, // pgroups linked to the contact
associatedPgroups: associatedPgroups || [], // Ensure associatedPgroups is always an array
};
});
@ -168,30 +169,30 @@ const ContactsManager: React.FC<ContactsManagerProps> = ({ pgroups, activePgroup
const renderPgroupChips = (contact: ContactWithPgroups) => {
return pgroups.map((pgroup) => {
const isAssociated = contact.associatedPgroups.includes(pgroup);
const isAssociated = (contact.associatedPgroups ?? []).includes(pgroup); // Ensure default empty array
return (
<Chip
key={pgroup}
label={pgroup}
onClick={
!isAssociated
? () => togglePgroupAssociation(contact.id, pgroup)
: undefined
}
sx={{
backgroundColor: isAssociated ? '#19d238' : '#b0b0b0',
color: 'white',
borderRadius: '8px',
fontWeight: 'bold',
height: '20px',
fontSize: '12px',
boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)',
cursor: isAssociated ? 'default' : 'pointer', // Disable pointer for associated chips
'&:hover': { opacity: isAssociated ? 1 : 0.8 }, // Disable hover effect for associated chips
mr: 1,
mb: 1,
}}
/>
<Chip
key={pgroup}
label={pgroup}
onClick={
!isAssociated
? () => togglePgroupAssociation(contact.id, pgroup)
: undefined
}
sx={{
backgroundColor: isAssociated ? '#19d238' : '#b0b0b0',
color: 'white',
borderRadius: '8px',
fontWeight: 'bold',
height: '20px',
fontSize: '12px',
boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)',
cursor: isAssociated ? 'default' : 'pointer', // Disable pointer for associated chips
'&:hover': { opacity: isAssociated ? 1 : 0.8 }, // Disable hover effect for associated chips
mr: 1,
mb: 1,
}}
/>
);
});
};
@ -202,6 +203,13 @@ const ContactsManager: React.FC<ContactsManagerProps> = ({ pgroups, activePgroup
Contacts Management
</Typography>
<Box mb={3} display="flex" justifyContent="center" alignItems="center">
<TextField
label="pgroup"
name="pgroup"
value={newContact.pgroups || ''}
disabled
sx={{ width: '120px' }} // Small fixed-size for non-editable field
/>
<TextField
label="First Name"
name="firstname"
@ -233,28 +241,30 @@ const ContactsManager: React.FC<ContactsManagerProps> = ({ pgroups, activePgroup
{errorMessage && <Typography color="error">{errorMessage}</Typography>}
<List>
{contacts.length > 0 ? (
contacts.map((contact) => (
<ListItem key={contact.id} button>
<ListItemText
primary={`${contact.firstname} ${contact.lastname}`}
secondary={
<Box display="flex" flexWrap="wrap">
{renderPgroupChips(contact)}
</Box>
}
/>
<ListItemSecondaryAction>
<IconButton edge="end" color="primary" onClick={() => handleEditContact(contact)}>
<EditIcon />
</IconButton>
<IconButton edge="end" color="secondary" onClick={() => openDialog(contact)}>
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
))
contacts.map((contact) => (
<ListItem key={contact.id} button>
<ListItemText
primary={`${contact.firstname} ${contact.lastname}`}
secondary={
<Box display="flex" flexWrap="wrap">
{contact.associatedPgroups
? renderPgroupChips(contact) // Render chips only if associatedPgroups exists
: null}
</Box>
}
/>
<ListItemSecondaryAction>
<IconButton edge="end" color="primary" onClick={() => handleEditContact(contact)}>
<EditIcon />
</IconButton>
<IconButton edge="end" color="secondary" onClick={() => openDialog(contact)}>
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
))
) : (
<Typography>No contacts found</Typography>
<Typography>No contacts found</Typography>
)}
</List>
<Dialog