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';
|
currentView: View = 'signIn';
|
||||||
user: User | null = null;
|
user: User | null = null;
|
||||||
group: Group | null = null;
|
group: Group | null = null;
|
||||||
|
groupMembers: User[] = [];
|
||||||
|
|
||||||
setCurrentView = (view: View) => {
|
setCurrentView = (view: View) => {
|
||||||
this.currentView = view;
|
this.currentView = view;
|
||||||
@@ -32,6 +33,10 @@ export class Store {
|
|||||||
this.group = group;
|
this.group = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setGroupMembers = (members: User[]) => {
|
||||||
|
this.groupMembers = members;
|
||||||
|
}
|
||||||
|
|
||||||
logout = () => {
|
logout = () => {
|
||||||
void cookieStore.delete('user');
|
void cookieStore.delete('user');
|
||||||
void cookieStore.delete('group');
|
void cookieStore.delete('group');
|
||||||
|
|||||||
@@ -4,13 +4,26 @@ import Stack from '@mui/material/Stack';
|
|||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import Card from './Card';
|
import Card from './Card';
|
||||||
import { useStore } from '../Store';
|
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 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 Group = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const { group, logout } = store;
|
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) {
|
if (!group) {
|
||||||
return (<Typography>Keine Gruppe gefunden.</Typography>);
|
return (<Typography>Keine Gruppe gefunden.</Typography>);
|
||||||
@@ -46,11 +59,39 @@ const Group = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography>
|
<Typography>
|
||||||
{'Willkommen in der Gruppe!'}
|
{`Aktuelle Phase: ${group.phase}`}
|
||||||
</Typography>
|
|
||||||
<Typography>
|
|
||||||
{'Admin: ' + group.mail}
|
|
||||||
</Typography>
|
</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>
|
</Box>
|
||||||
</Card>
|
</Card>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { useTheme } from '@mui/material/styles';
|
|||||||
import GroupAddIcon from '@mui/icons-material/GroupAdd';
|
import GroupAddIcon from '@mui/icons-material/GroupAdd';
|
||||||
import ForgotPassword from '../ForgotPassword';
|
import ForgotPassword from '../ForgotPassword';
|
||||||
import Card from '../Card';
|
import Card from '../Card';
|
||||||
import { createUser, fetchGroupByCode, fetchUser } from '../../serverApi';
|
import { addUserToGroup, createUser, fetchGroupByCode, fetchUser } from '../../serverApi';
|
||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
import { useStore } from '../../Store';
|
import { useStore } from '../../Store';
|
||||||
|
|
||||||
@@ -64,6 +64,8 @@ const SignIn = observer(() => {
|
|||||||
if (!user) throw new Error('Error creating user');
|
if (!user) throw new Error('Error creating user');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await addUserToGroup(groupData.id, user.id);
|
||||||
|
|
||||||
await cookieStore.set('user', JSON.stringify(user));
|
await cookieStore.set('user', JSON.stringify(user));
|
||||||
await cookieStore.set('group', JSON.stringify(groupData));
|
await cookieStore.set('group', JSON.stringify(groupData));
|
||||||
setGroup(groupData);
|
setGroup(groupData);
|
||||||
|
|||||||
@@ -59,3 +59,33 @@ export async function createGroup(group: Partial<Group>): Promise<Group | null>
|
|||||||
return null;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/index.ts
14
src/index.ts
@@ -60,6 +60,20 @@ const server = serve({
|
|||||||
console.log('Fetching members for group ID:', groupId, 'Result:', members);
|
console.log('Fetching members for group ID:', groupId, 'Result:', members);
|
||||||
return new Response(JSON.stringify(members), { headers: { 'Content-Type': 'application/json' } });
|
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' && {
|
development: process.env.NODE_ENV !== 'production' && {
|
||||||
|
|||||||
@@ -157,6 +157,14 @@ class DB {
|
|||||||
return users;
|
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') {
|
constructor(url: string = './data.sqlite') {
|
||||||
this.instance = new SQL(url, {adapter: 'sqlite'});
|
this.instance = new SQL(url, {adapter: 'sqlite'});
|
||||||
this.prepareDB();
|
this.prepareDB();
|
||||||
|
|||||||
Reference in New Issue
Block a user