add member view to group
This commit is contained in:
BIN
data.sqlite
BIN
data.sqlite
Binary file not shown.
@@ -15,6 +15,7 @@ export class Store {
|
||||
currentView: View = 'signIn';
|
||||
user: User | null = null;
|
||||
group: Group | null = null;
|
||||
groupMembers: User[] = [];
|
||||
|
||||
setCurrentView = (view: View) => {
|
||||
this.currentView = view;
|
||||
@@ -32,6 +33,10 @@ export class Store {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
setGroupMembers = (members: User[]) => {
|
||||
this.groupMembers = members;
|
||||
}
|
||||
|
||||
logout = () => {
|
||||
void cookieStore.delete('user');
|
||||
void cookieStore.delete('group');
|
||||
|
||||
@@ -4,13 +4,26 @@ import Stack from '@mui/material/Stack';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import Card from './Card';
|
||||
import { useStore } from '../Store';
|
||||
import { CardHeader, IconButton } from '@mui/material';
|
||||
import { Avatar, CardHeader, IconButton, List, ListItem, ListItemAvatar, ListItemText, ListSubheader } from '@mui/material';
|
||||
import LogoutIcon from '@mui/icons-material/Logout';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { fetchGroupMembers } from '../serverApi';
|
||||
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
||||
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
||||
|
||||
const Group = () => {
|
||||
const theme = useTheme();
|
||||
const store = useStore();
|
||||
const { group, logout } = store;
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
void fetchGroupMembers(group?.id ?? 0).then(members => {
|
||||
store.setGroupMembers(members);
|
||||
setLoading(false);
|
||||
});
|
||||
}, [group]);
|
||||
|
||||
if (!group) {
|
||||
return (<Typography>Keine Gruppe gefunden.</Typography>);
|
||||
@@ -46,11 +59,39 @@ const Group = () => {
|
||||
}}
|
||||
>
|
||||
<Typography>
|
||||
{'Willkommen in der Gruppe!'}
|
||||
</Typography>
|
||||
<Typography>
|
||||
{'Admin: ' + group.mail}
|
||||
{`Aktuelle Phase: ${group.phase}`}
|
||||
</Typography>
|
||||
<List
|
||||
sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}
|
||||
component="nav"
|
||||
aria-labelledby="nested-list-subheader"
|
||||
subheader={
|
||||
<ListSubheader component="div" id="nested-list-subheader">
|
||||
Mitglieder
|
||||
</ListSubheader>
|
||||
}
|
||||
dense={true}
|
||||
>
|
||||
{store.groupMembers.map((member) => (
|
||||
<ListItem
|
||||
key={member.id}
|
||||
secondaryAction={
|
||||
<IconButton edge="end" aria-label="delete">
|
||||
<MoreHorizIcon />
|
||||
</IconButton>
|
||||
}
|
||||
>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
<AccountCircleIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={member.mail}
|
||||
secondary={member.mail === group.mail ? 'Admin' : 'Mitglied'}
|
||||
/>
|
||||
</ListItem>))}
|
||||
</List>
|
||||
</Box>
|
||||
</Card>
|
||||
</Stack>
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useTheme } from '@mui/material/styles';
|
||||
import GroupAddIcon from '@mui/icons-material/GroupAdd';
|
||||
import ForgotPassword from '../ForgotPassword';
|
||||
import Card from '../Card';
|
||||
import { createUser, fetchGroupByCode, fetchUser } from '../../serverApi';
|
||||
import { addUserToGroup, createUser, fetchGroupByCode, fetchUser } from '../../serverApi';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from '../../Store';
|
||||
|
||||
@@ -64,6 +64,8 @@ const SignIn = observer(() => {
|
||||
if (!user) throw new Error('Error creating user');
|
||||
}
|
||||
|
||||
await addUserToGroup(groupData.id, user.id);
|
||||
|
||||
await cookieStore.set('user', JSON.stringify(user));
|
||||
await cookieStore.set('group', JSON.stringify(groupData));
|
||||
setGroup(groupData);
|
||||
|
||||
@@ -58,4 +58,34 @@ export async function createGroup(group: Partial<Group>): Promise<Group | null>
|
||||
console.error('Failed to create group:', err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchGroupMembers(groupId: number): Promise<User[]> {
|
||||
try {
|
||||
const res = await fetch(`/api/group_members/${groupId}`);
|
||||
if (!res.ok) return [];
|
||||
const data: User[] = await res.json();
|
||||
return data;
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch group members:', err);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function addUserToGroup(groupId: number, userId: number): Promise<{ id: number | bigint; } | null> {
|
||||
try {
|
||||
const res = await fetch('/api/group_members', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ groupId, userId }),
|
||||
});
|
||||
if (!res.ok) return null;
|
||||
const data: { id: number | bigint; } = await res.json();
|
||||
return data;
|
||||
} catch (err) {
|
||||
console.error('Failed to add user to group:', err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
16
src/index.ts
16
src/index.ts
@@ -60,10 +60,24 @@ const server = serve({
|
||||
console.log('Fetching members for group ID:', groupId, 'Result:', members);
|
||||
return new Response(JSON.stringify(members), { headers: { 'Content-Type': 'application/json' } });
|
||||
},
|
||||
|
||||
'/api/group_members': {
|
||||
async POST(req) {
|
||||
try {
|
||||
const { groupId, userId } = await req.json() as { groupId: number; userId: number };
|
||||
console.log('Received request to add user ID ', userId, 'to group ID:', groupId);
|
||||
const response = await db.addUserToGroup(groupId, userId);
|
||||
return new Response(JSON.stringify(response), { headers: { 'Content-Type': 'application/json' } });
|
||||
} catch (err) {
|
||||
console.error('Error adding user to group:', err);
|
||||
return new Response(JSON.stringify({ error: 'Failed to add user to group' }), { status: 500 });
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
development: process.env.NODE_ENV !== 'production' && {
|
||||
// Enable browser hot reloading in development
|
||||
// Enable browser hot reloading in development
|
||||
hmr: true,
|
||||
|
||||
// Echo console logs from the browser to the server
|
||||
|
||||
@@ -157,6 +157,14 @@ class DB {
|
||||
return users;
|
||||
}
|
||||
|
||||
public async addUserToGroup(groupId: number, userId: number): Promise<{ id: number | bigint; } | null> {
|
||||
const membership: { id: number | bigint;}[] = await this.instance`
|
||||
INSERT OR IGNORE INTO membership (group_id, user_id) VALUES (${groupId}, ${userId})
|
||||
RETURNING *
|
||||
`;
|
||||
return membership[0] ?? null;
|
||||
}
|
||||
|
||||
constructor(url: string = './data.sqlite') {
|
||||
this.instance = new SQL(url, {adapter: 'sqlite'});
|
||||
this.prepareDB();
|
||||
|
||||
Reference in New Issue
Block a user