rendering membership modal

This commit is contained in:
balzack 2024-12-22 22:01:00 -08:00
parent deb61ac89e
commit 597b850be4
3 changed files with 87 additions and 22 deletions

View File

@ -161,21 +161,38 @@
}
}
}
}
.card {
width: 100%;
height: 48px;
padding-top: 8px;
padding-bottom: 8px;
padding-right: 16px;
padding-left: 16px;
border-bottom: 1px solid var(--mantine-color-text-8);
}
.card {
width: 100%;
height: 48px;
padding-top: 8px;
padding-bottom: 8px;
padding-right: 16px;
padding-left: 16px;
border-bottom: 1px solid var(--mantine-color-text-8);
}
.cards {
min-width: 0;
.cards {
min-width: 0;
width: 100%;
flex-shrink: 1;
overflow: auto;
}
.modalContainer {
.cardMembers {
width: 100%;
flex-shrink: 1;
min-height: 128px;
max-height: 256px;
border: 1px solid var(--mantine-color-text-8);
overflow: auto;
}
.controls {
width: 100%;
display: flex;
justify-content: flex-end;
padding-top: 8px;
}
}

View File

@ -2,7 +2,7 @@ import React, { useState } from 'react'
import { useDetails } from './useDetails.hook'
import classes from './Details.module.css'
import { IconUserCog, IconEyeOff, IconAlertHexagon, IconMessageX, IconLogout2, IconHome, IconServer, IconShield, IconShieldOff, IconCalendarClock, IconExclamationCircle, IconX, IconEdit, IconDeviceFloppy, IconArrowBack, IconLabel } from '@tabler/icons-react'
import { Divider, Text, Textarea, Image, TextInput, ActionIcon } from '@mantine/core'
import { Switch, Button, Modal, Divider, Text, Textarea, Image, TextInput, ActionIcon } from '@mantine/core'
import { Card } from '../card/Card';
import { modals } from '@mantine/modals'
@ -12,6 +12,7 @@ export function Details({ close }: { close: () => void }) {
const [removing, setRemoving] = useState(false);
const [blocking, setBlocking] = useState(false);
const [reporting, setReporting] = useState(false);
const [showModal, setShowModal] = useState(false);
const undo = () => {
actions.undoSubject();
@ -153,6 +154,37 @@ export function Details({ close }: { close: () => void }) {
handle={card.handle} node={card.node} actions={[]} />
))
const members = state.cards.filter(card => {
if (state.detail && state.detail.members.find(member => member.guid === card.guid)) {
return true;
} else if(state.sealed && !card.sealable) {
return false;
} else {
return true;
}
}).map((card, index) => {
const enable = (
<Switch
key="enable"
className={classes.setMember}
size="sm"
checked={Boolean(state.detail.members.find(member => member.guid === card.guid))}
onChange={(ev) => {
if (ev.currentTarget.checked) {
console.log("ADD MEMBER");
} else {
console.log("REMOVE MEMBER");
}
}}
/>
)
return (
<Card className={classes.card} key={index} imageUrl={card.imageUrl} name={card.name} placeholder={state.strings.name}
handle={card.handle} node={card.node} actions={[enable]} />
)
});
return (
<div className={classes.details}>
<div className={classes.header}>
@ -254,7 +286,7 @@ export function Details({ close }: { close: () => void }) {
<Text className={classes.actionLabel}>{state.strings.remove}</Text>
</div>
<div className={classes.action}>
<ActionIcon variant="subtle" size={32} >
<ActionIcon variant="subtle" size={32} onClick={()=>setShowModal(true)}>
<IconUserCog size={32} />
</ActionIcon>
<Text className={classes.actionLabel}>{state.strings.members}</Text>
@ -287,6 +319,18 @@ export function Details({ close }: { close: () => void }) {
<Text>{ state.strings.syncError }</Text>
</div>
)}
<Modal title={state.strings.editMembership} opened={showModal} onClose={() => setShowModal(false)} overlayProps={{ backgroundOpacity: 0.65, blur: 3 }} centered>
<div className={classes.modalContainer}>
<div className={classes.cardMembers}>
{ members }
</div>
<div className={classes.controls}>
<Button variant="default" onClick={() => setShowModal(false)}>
{state.strings.close}
</Button>
</div>
</div>
</Modal>
</div>
)
}

View File

@ -22,7 +22,7 @@ export function useDetails() {
editSubject: '',
created: '',
profile: null as null | Profile,
cards: new Map<string, Card>(),
cards: [] as Card[],
hostCard: null as null | Card,
channelCards: [] as Card[],
unknownContacts: 0,
@ -69,10 +69,9 @@ export function useDetails() {
}, [display.state]);
useEffect(() => {
const cards = Array.from(state.cards.values());
const hostCard = cards.find(entry => entry.cardId == state.cardId);
const hostCard = state.cards.find(entry => entry.cardId == state.cardId);
const profileRemoved = state.detail?.members ? state.detail.members.filter(member => state.profile?.guid != member.guid) : [];
const contactCards = profileRemoved.map(member => state.cards.get(member.guid));
const contactCards = profileRemoved.map(member => state.cards.find(card => card.guid === member.guid));
const channelCards = contactCards.filter(member => Boolean(member));
const unknownContacts = contactCards.length - channelCards.length;
updateState({ hostCard, channelCards, unknownContacts });
@ -83,11 +82,16 @@ export function useDetails() {
const { contact, identity } = app.state.session || { };
if (focus && contact && identity) {
const setCards = (cards: Card[]) => {
const contacts = new Map<string, Card>();
cards.forEach(card => {
contacts.set(card.guid, card);
const sorted = cards.sort((a, b) => {
if (a.handle > b.handle) {
return 1;
} else if (a.handle < b.handle) {
return -1;
} else {
return 0;
}
});
updateState({ cards: contacts });
updateState({ cards: sorted });
}
const setProfile = (profile: Profile) => {
updateState({ profile });