2024-06-24 13:11:20 +02:00

224 lines
7.4 KiB
TypeScript

import { useNavigate, useParams } from "@solidjs/router";
import { Component, Show, createEffect, createSignal } from "solid-js";
import styles from './GroupPage.module.css'
import { Group, Map, Profile, Strat, User, api } from "../api";
import { showDialog, showInputDialog, showMessageDialog } from "../state";
import { _arrayBufferToBase64, errorToString, normalize } from "../util";
import { BsCheck2, BsPencil, BsTrash } from "solid-icons/bs";
import { Collapse } from "solid-collapse";
import MemberItem from "../components/MemberItem";
import MapItem from "../components/MapItem";
import StratItem from "../components/StratItem";
import StratTypeItem from "../components/StratTypeItem";
import ProfileItem from "../components/ProfileItem";
import { UploadFile, createFileUploader } from "@solid-primitives/upload";
const GroupPage: Component = () => {
const params = useParams();
const navigate = useNavigate();
const [loading, setLoading] = createSignal(true);
const [group, setGroup] = createSignal({} as Group);
const [editing, setEditing] = createSignal(false);
const [name, setName] = createSignal('');
const [membersIsExpanded, setMembersIsExpanded] = createSignal(false);
const [mapsIsExpanded, setMapsIsExpanded] = createSignal(false);
const [stratsIsExpanded, setStratsIsExpanded] = createSignal(false);
const [profilesIsExpanded, setProfilesIsExpanded] = createSignal(false);
const [stratTypesIsExpanded, setStratTypesIsExpanded] = createSignal(false);
createEffect(async () => {
try {
setGroup(await api().getGroup(params.id));
setName(group().name);
setLoading(false);
} catch (e) {
showMessageDialog('Failed to load group', errorToString(e));
}
}, []);
const updateGroup = async (newValue: Group) => {
try {
await api().updateGroup(group().id, newValue);
setGroup(newValue);
} catch (e) {
showMessageDialog('Failed to update group', errorToString(e));
}
};
const deleteGroup = async () => {
showDialog({
title: 'Delete group',
text: 'Do you want to delete this group?',
buttons: [
{
name: 'Delete',
type: 'danger',
action: async () => {
try {
await api().removeGroup(group().id);
navigate('/groups');
} catch (e) {
showMessageDialog('Failed to delete group', errorToString(e));
}
}
},
{
name: 'Cancel',
action: () => { }
}
]
});
};
const addMember = async () => {
showInputDialog('Add member to Group', 'enter the member id you want to add', 'member ID', async (memberId) => {
try {
const newGroup = await api().addMember(group().id, memberId);
setGroup(newGroup);
} catch (e) {
showMessageDialog('Failed to add member', errorToString(e));
}
})
};
const addStratType = async () => {
showInputDialog('Add strat type to Group', 'enter the name you want to add', 'strat type', async (stratType) => {
try {
const newGroup = await api().addStratType(group().id, stratType);
setGroup(newGroup);
} catch (e) {
showMessageDialog('Failed to add strat type', errorToString(e));
}
})
};
const addProfile = async () => {
const [profileName, setProfileName] = createSignal('');
const { files, selectFiles } = createFileUploader({
multiple: false,
accept: "image/*",
});
let fileReader = new FileReader();
fileReader.onload = async event => {
try {
const newGroup = await api().addProfileToGroup(group().id, { name: profileName(), image: _arrayBufferToBase64(event.target!.result as ArrayBuffer) });
setGroup(newGroup);
} catch (e) {
showMessageDialog('Failed to add profile', errorToString(e));
}
}
showDialog({
title: 'Add profile to Group',
text: 'create a new profile',
inputFields: [{
onInput: setProfileName,
placeholder: 'name'
}],
onDismiss: async () => {
fileReader.readAsArrayBuffer(files()[0].file);
},
buttons: [{
name: 'add image', action: () => selectFiles(([{ source, name, size, file }]) => {
console.log({ source, name, size, file });
}),
closeOnClick: false
},
'confirm'
],
})
};
const toggleEdit = async () => {
if (!editing()) {
setEditing(true);
} else {
console.log(name());
updateGroup({ ...group(), name: name() });
setEditing(false);
}
};
const onDeleteMember = async (member: User) => {
setGroup({ ...group(), members: [...group().members.filter(m => m.username !== member.username)] });
};
const onDeleteMap = async (map: Map) => {
setGroup({ ...group(), maps: [...group().maps.filter(m => m.id !== map.id)] });
};
const onDeleteStrat = async (strat: Strat) => {
setGroup({ ...group(), strats: [...group().strats.filter(s => s.id !== strat.id)] });
};
const onDeleteStratType = async (stratType: string) => {
setGroup({ ...group(), stratTypes: [...group().stratTypes.filter(s => s !== stratType)] });
};
const onDeleteProfile = async (profile: Profile) => {
setGroup({ ...group(), profiles: [...group().profiles.filter(p => p.id !== profile.id)] });
};
return (
<>
<Show when={!loading()} fallback={<div>Loading...</div>}>
<div class={styles.groupName}>
<span contentEditable={editing()} innerText={group().name} onInput={e => setName(normalize(e.currentTarget.innerText, 50, true))} />
{editing() && <span class={styles.editCount}>{name().length}/50</span>}
</div>
<div class={styles.groupButtons}>
<button class={styles.deleteButton} onClick={deleteGroup}>Delete group</button>
<button class={styles.editButton} onClick={toggleEdit}>{editing() ? <BsCheck2 /> : <BsPencil />}</button>
</div>
<hr />
<div>
<button onClick={() => setMembersIsExpanded(!membersIsExpanded())}>Members</button>
<button class={styles.addMemberButton} onClick={addMember}>+</button>
<Collapse value={membersIsExpanded()} class={styles.members}>
<div class={styles.groupMembers}>
{group().members?.map(m => <MemberItem group={group()} member={m} onDelete={onDeleteMember} />)}
</div>
</Collapse>
<br />
<button onClick={() => setStratsIsExpanded(!stratsIsExpanded())}>strats</button>
<Collapse value={stratsIsExpanded()} class={styles.strats}>
<div class={styles.strats}>
{group().strats?.map(s => <StratItem group={group()} strat={s} onDelete={onDeleteStrat} />)}
</div>
</Collapse>
<br />
<button onClick={() => setMapsIsExpanded(!mapsIsExpanded())}>maps</button>
<Collapse value={mapsIsExpanded()} class={styles.maps}>
<div class={styles.maps}>
{group().maps?.map(m => <MapItem group={group()} map={m} onDelete={onDeleteMap} />)}
</div>
</Collapse>
<br />
<button onClick={() => setStratTypesIsExpanded(!stratTypesIsExpanded())}>strat types</button>
<button class={styles.addMemberButton} onClick={addStratType}>+</button>
<Collapse value={stratTypesIsExpanded()} class={styles.stratTypes}>
<div class={styles.stratTypes}>
{group().stratTypes?.map(s => <StratTypeItem group={group()} stratType={s} onDelete={onDeleteStratType} />)}
</div>
</Collapse>
<br />
<button onClick={() => setProfilesIsExpanded(!profilesIsExpanded())}>profiles</button>
<button class={styles.addMemberButton} onClick={addProfile}>+</button>
<Collapse value={profilesIsExpanded()} class={styles.profiles}>
<div class={styles.profiles}>
{group().profiles?.map(p => <ProfileItem group={group()} profile={p} onDelete={onDeleteProfile} />)}
</div>
</Collapse>
</div>
</Show>
</>
)
}
export default GroupPage;