chore: add all the code from original repo

This commit is contained in:
Riccardo
2024-05-23 16:55:29 +02:00
parent d8f9a215eb
commit 85d66215a7
66 changed files with 16668 additions and 122 deletions

View File

@@ -0,0 +1,101 @@
import {
Box,
Stack,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
TextField,
Typography
} from '@mui/material';
import { nanoid } from 'nanoid';
import { Dispatch, useEffect, useState } from 'react';
import { useFormState } from 'react-dom';
import { Profiles } from '../../../../data/types';
import { CreateProfileAction } from './actions/CreateProfileAction';
import { ProfilesAction } from './actions/ProfilesAction';
import ProfilesTableRow from './ProfilesTableRow';
interface ProfilesTableProps {
selectedProfile: string | undefined;
setSelectedProfile: Dispatch<string | undefined>;
}
export default function ProfilesTable({
selectedProfile,
setSelectedProfile
}: ProfilesTableProps) {
const [profiles, setProfiles] = useState<Profiles>([]);
const [formKey, setFormKey] = useState(() => nanoid());
const [refreshKey, setRefreshKey] = useState(0);
const [formState, formAction] = useFormState(CreateProfileAction, {
clear: false
});
useEffect(() => {
const fetchProfiles = async () => {
try {
const profiles = await ProfilesAction();
setProfiles(profiles);
} catch (error) {
console.error("Couldn't fetch profiles.");
}
};
if (formState.clear) {
setFormKey(nanoid());
}
fetchProfiles();
}, [formState, refreshKey]);
return (
<Stack
sx={{
spacing: 2,
padding: 2
}}
>
<Typography variant="h6">Profiles</Typography>
<Box>
<form key={formKey} action={formAction}>
<TextField fullWidth name="name" placeholder="Add new profile" />
</form>
<Box
sx={{
maxHeight: 'calc(100vh - 200px)',
overflow: 'auto'
}}
>
<Table
stickyHeader
sx={{
width: '100%'
}}
>
<TableHead>
<TableRow sx={{ '& th': { textAlign: 'center' } }}>
<TableCell>Name</TableCell>
<TableCell>Delete</TableCell>
</TableRow>
</TableHead>
<TableBody>
{profiles &&
profiles.map((profile) => (
<ProfilesTableRow
key={profile.id}
profile={profile}
selected={selectedProfile}
setSelected={setSelectedProfile}
onDelete={() => setRefreshKey((prevKey) => prevKey + 1)}
/>
))}
</TableBody>
</Table>
</Box>
</Box>
</Stack>
);
}

View File

@@ -0,0 +1,81 @@
import { Button, TableCell, TableRow, TextField } from '@mui/material';
import { Dispatch, useState } from 'react';
import { Profile } from '../../../../data/types';
import { DeleteProfileAction } from './actions/DeleteProfileAction';
import { UpdateProfileAction } from './actions/UpdateProfileAction';
interface ProfilesTableRowProps {
profile: Profile;
selected: string | undefined;
setSelected: Dispatch<string | undefined>;
onDelete: () => void;
}
export default function ProfilesTableRow({
profile,
selected,
setSelected,
onDelete
}: ProfilesTableRowProps) {
const [isEditing, setIsEditing] = useState(false);
const [name, setName] = useState(profile.name);
const handleClick = () => {
setSelected(profile.id);
};
const handleDoubleClick = () => {
setIsEditing(true);
};
const handleBlur = async () => {
setIsEditing(false);
try {
await UpdateProfileAction({
id: profile.id,
name
});
} catch (error) {
console.error("Couldn't update profile.");
}
};
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
const handleDelete = async () => {
try {
await DeleteProfileAction(profile.id);
onDelete();
} catch (error) {
console.error("Couldn't delete profile.");
}
};
return (
<TableRow key={profile.id}>
<TableCell
align="center"
onClick={handleClick}
onDoubleClick={handleDoubleClick}
sx={{ bgcolor: profile.id === selected ? 'lightblue' : 'inherit' }}
>
{isEditing ? (
<TextField
value={name}
onChange={handleChange}
onBlur={handleBlur}
autoFocus
/>
) : (
name
)}
</TableCell>
<TableCell align="center">
<Button onClick={handleDelete}>Delete</Button>
</TableCell>
</TableRow>
);
}

View File

@@ -0,0 +1,53 @@
'use server';
import { initializeUser } from '../../../../../data/initializeUser';
import { CreateProfileFormSchema } from '../../../../../data/types';
import prisma from '../../../../../prisma/prisma';
interface CreateItemActionProps {
clear: boolean;
error?: string;
}
export async function CreateProfileAction(
_: CreateItemActionProps,
formData: FormData
) {
const formDataObj = Object.fromEntries(formData.entries());
const validatedBody = CreateProfileFormSchema.safeParse(formDataObj);
if (!validatedBody.success) {
throw new Error('Bad request');
}
const user = await initializeUser();
try {
const existingProfile = await prisma.profile.findFirst({
where: {
userId: user.id,
name: validatedBody.data.name
}
});
if (existingProfile) {
return { clear: false };
}
} catch (error) {
throw new Error(`Failed to find profile`);
}
try {
await prisma.profile.create({
data: {
userId: user.id,
name: validatedBody.data.name
}
});
return { clear: true };
} catch (error) {
throw new Error(`Failed to create profile`);
}
}

View File

@@ -0,0 +1,22 @@
'use server';
import { z } from 'zod';
import prisma from '../../../../../prisma/prisma';
export async function DeleteProfileAction(id: string) {
const validatedBody = z.string().safeParse(id);
if (!validatedBody.success) {
throw new Error('Bad request');
}
try {
await prisma.profile.delete({
where: {
id
}
});
} catch (error) {
throw new Error(`Failed to delete profile`);
}
}

View File

@@ -0,0 +1,23 @@
'use server';
import { initializeUser } from '../../../../../data/initializeUser';
import prisma from '../../../../../prisma/prisma';
export async function ProfilesAction() {
const user = await initializeUser();
try {
const profiles = await prisma.profile.findMany({
where: {
userId: user.id
},
orderBy: {
createdAt: 'desc'
}
});
return profiles;
} catch (error) {
throw new Error('Failed to find profiles');
}
}

View File

@@ -0,0 +1,31 @@
'use server';
import { z } from 'zod';
import prisma from '../../../../../prisma/prisma';
interface ProfileActionProps {
id: string;
name: string;
error?: string;
}
export async function UpdateProfileAction({ id, name }: ProfileActionProps) {
const validatedBody = z.string().safeParse(name);
if (!validatedBody.success) {
throw new Error('Bad request');
}
try {
await prisma.profile.update({
where: {
id
},
data: {
name: validatedBody.data
}
});
} catch (error) {
throw new Error(`Failed to update profile`);
}
}