chore: add all the code from original repo
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { CreateButton } from '@/components/UI/CreateButton';
|
||||
import { Checkbox, FormControlLabel, Stack, TextField } from '@mui/material';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { useEffect } from 'react';
|
||||
import { useFormState } from 'react-dom';
|
||||
import { CreateCommentAction } from './actions/CreateCommentAction';
|
||||
|
||||
interface CreateCommentProps {
|
||||
itemId: string;
|
||||
setFormKey: (key: string) => void;
|
||||
}
|
||||
|
||||
export default function CreateComment({
|
||||
itemId,
|
||||
setFormKey
|
||||
}: CreateCommentProps) {
|
||||
const [formState, formAction] = useFormState(CreateCommentAction, {
|
||||
itemId,
|
||||
clear: false
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (formState.clear) {
|
||||
setFormKey(nanoid());
|
||||
}
|
||||
}, [setFormKey, formState]);
|
||||
|
||||
return (
|
||||
<form action={formAction}>
|
||||
<Stack spacing={2} marginY={2}>
|
||||
<TextField name="body" label="Comment" variant="outlined" required />
|
||||
<TextField
|
||||
name="score"
|
||||
label="Score"
|
||||
variant="outlined"
|
||||
type="number"
|
||||
inputProps={{ step: 1, min: 0, max: 10 }}
|
||||
/>
|
||||
<FormControlLabel name="regret" control={<Checkbox />} label="Regret" />
|
||||
<CreateButton />
|
||||
</Stack>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
'use server';
|
||||
|
||||
import { CreateCommentFormSchema } from '../../../../../../data/types';
|
||||
import prisma from '../../../../../../prisma/prisma';
|
||||
|
||||
interface ItemDialogActionProps {
|
||||
clear: boolean;
|
||||
itemId: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export async function CreateCommentAction(
|
||||
{ itemId }: ItemDialogActionProps,
|
||||
formData: FormData
|
||||
) {
|
||||
const formDataObj = Object.fromEntries(formData.entries());
|
||||
|
||||
const validatedBody = CreateCommentFormSchema.safeParse(formDataObj);
|
||||
|
||||
if (!validatedBody.success) {
|
||||
throw new Error('Bad request');
|
||||
}
|
||||
|
||||
const { body, score, regret } = validatedBody.data;
|
||||
|
||||
try {
|
||||
await prisma.itemComment.create({
|
||||
data: {
|
||||
body,
|
||||
score,
|
||||
regret,
|
||||
Item: {
|
||||
connect: {
|
||||
id: itemId
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to create comment`);
|
||||
}
|
||||
|
||||
return { clear: true, itemId };
|
||||
}
|
||||
39
app/components/Dashboard/ItemDialog/ItemData.tsx
Normal file
39
app/components/Dashboard/ItemDialog/ItemData.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Card, Typography } from '@mui/material';
|
||||
import { Box } from '@mui/system';
|
||||
import { Item, ItemComment } from '../../../../data/types';
|
||||
|
||||
interface ItemDataProps {
|
||||
item: Item;
|
||||
comments: ItemComment[];
|
||||
}
|
||||
|
||||
export default function ItemData({ item, comments }: ItemDataProps) {
|
||||
return (
|
||||
<Box>
|
||||
<Typography>Description: {item.description}</Typography>
|
||||
<Typography>
|
||||
Price: {Number(item.price).toFixed(2)} {item.currency}
|
||||
</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
height: 250,
|
||||
overflowY: 'auto'
|
||||
}}
|
||||
>
|
||||
{comments &&
|
||||
comments.map((comment) => (
|
||||
<Card key={comment.id} sx={{ margin: '5px', padding: '10px' }}>
|
||||
<Typography>Comment: {comment.body}</Typography>
|
||||
<Typography>Score: {comment.score}</Typography>
|
||||
<Typography>Regret: {comment.regret ? 'Yes' : 'No'}</Typography>
|
||||
<Typography>
|
||||
Created:{' '}
|
||||
{comment.createdAt &&
|
||||
new Date(comment.createdAt).toLocaleString()}
|
||||
</Typography>
|
||||
</Card>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
53
app/components/Dashboard/ItemDialog/ItemDialog.tsx
Normal file
53
app/components/Dashboard/ItemDialog/ItemDialog.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Button, Dialog, DialogContent, DialogTitle } from '@mui/material';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { Item, ItemComment } from '../../../../data/types';
|
||||
import { ItemsTableRowAction } from '../Items/ItemsTableRowAction';
|
||||
import CreateComment from './CreateComment/CreateComment';
|
||||
import ItemData from './ItemData';
|
||||
|
||||
interface ItemDialogProps {
|
||||
item: Item;
|
||||
open: boolean;
|
||||
handleClose: () => void;
|
||||
}
|
||||
|
||||
export default function ItemDialog({
|
||||
item,
|
||||
open,
|
||||
handleClose
|
||||
}: ItemDialogProps) {
|
||||
const [comments, setComments] = useState<ItemComment[]>([]);
|
||||
const [formKey, setFormKey] = useState(() => nanoid());
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
try {
|
||||
const comments = await ItemsTableRowAction(item.id);
|
||||
setComments(comments);
|
||||
} catch (error) {
|
||||
console.error("Couldn't fetch comments.");
|
||||
}
|
||||
}, [item]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [fetchData, formKey]);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={handleClose}>
|
||||
<DialogTitle sx={{ alignSelf: 'center' }}>Item: {item.name}</DialogTitle>
|
||||
<DialogContent sx={{ width: 400 }}>
|
||||
<ItemData item={item} comments={comments} />
|
||||
<CreateComment key={formKey} itemId={item.id} setFormKey={setFormKey} />
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={handleClose}
|
||||
sx={{ width: '100%' }}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user