chore: components cleanup
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
} from "@mui/material";
|
||||
import type { Announcement } from "../services";
|
||||
import { AnnouncementTableRow } from "./AnnouncementTableRow";
|
||||
|
||||
export interface AnnouncementTableProps {
|
||||
announcements: Announcement[];
|
||||
openDeleteConfirmation(announcement: Announcement): void;
|
||||
}
|
||||
|
||||
export function AnnouncementTable({
|
||||
announcements,
|
||||
openDeleteConfirmation,
|
||||
}: AnnouncementTableProps) {
|
||||
return (
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell />
|
||||
<TableCell>Title</TableCell>
|
||||
<TableCell>Text</TableCell>
|
||||
<TableCell>Publication Date</TableCell>
|
||||
<TableCell />
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{announcements.map((a) => (
|
||||
<AnnouncementTableRow
|
||||
key={a.id}
|
||||
announcement={a}
|
||||
openDeleteConfirmation={openDeleteConfirmation}
|
||||
/>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import { IconButton, TableCell, TableRow } from "@mui/material";
|
||||
import type { Announcement } from "../services";
|
||||
|
||||
export interface AnnouncementTableRowProps {
|
||||
announcement: Announcement;
|
||||
openDeleteConfirmation(announcement: Announcement): void;
|
||||
}
|
||||
|
||||
export function AnnouncementTableRow({
|
||||
openDeleteConfirmation,
|
||||
announcement,
|
||||
}: AnnouncementTableRowProps) {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell>{announcement.id}</TableCell>
|
||||
<TableCell>{announcement.title}</TableCell>
|
||||
<TableCell>
|
||||
{announcement.text.substring(0, 50) +
|
||||
(announcement.text.length > 50 ? "..." : "")}
|
||||
</TableCell>
|
||||
<TableCell>{announcement.publication_date.toString()}</TableCell>
|
||||
<TableCell>
|
||||
<IconButton onClick={() => openDeleteConfirmation(announcement)}>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
} from "@mui/material";
|
||||
import type { Announcement } from "../services";
|
||||
|
||||
export interface DeleteAnnouncementDialogProps {
|
||||
isDeleteConfirmationOpen: boolean;
|
||||
denyDelete(): void;
|
||||
confirmDelete(): void;
|
||||
announcement: Announcement;
|
||||
}
|
||||
|
||||
export function DeleteAnnouncementDialog({
|
||||
announcement,
|
||||
confirmDelete,
|
||||
denyDelete,
|
||||
isDeleteConfirmationOpen,
|
||||
}: DeleteAnnouncementDialogProps) {
|
||||
return (
|
||||
<Dialog
|
||||
open={isDeleteConfirmationOpen}
|
||||
onClose={denyDelete}
|
||||
role="alertdialog"
|
||||
>
|
||||
<DialogTitle>Delete announcement</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
Do you want to delete the announcement{" "}
|
||||
<strong>{announcement.title}</strong>?
|
||||
</DialogContentText>
|
||||
<DialogActions>
|
||||
<Button onClick={denyDelete} autoFocus>
|
||||
No
|
||||
</Button>
|
||||
<Button onClick={confirmDelete}>Yes</Button>
|
||||
</DialogActions>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
+17
-90
@@ -1,41 +1,12 @@
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { Alert, Box, CircularProgress, Typography } from "@mui/material";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import z from "zod";
|
||||
import { AnnouncementTable } from "../components/AnnouncementTable";
|
||||
import { DeleteAnnouncementDialog } from "../components/DeleteAnnouncementDialog";
|
||||
import { RouterButton } from "../components/RouterButton";
|
||||
import { useBoolean } from "../components/use-boolean";
|
||||
|
||||
const Announcements = z.array(
|
||||
z.object({
|
||||
id: z.number(),
|
||||
title: z.string(),
|
||||
text: z.string(),
|
||||
publication_date: z.iso.datetime().transform((arg) => new Date(arg)),
|
||||
image: z.string(),
|
||||
}),
|
||||
);
|
||||
|
||||
type Announcement = z.infer<typeof Announcements>[0];
|
||||
import { type Announcement, getAnnouncements } from "../services";
|
||||
|
||||
export const Route = createFileRoute("/")({
|
||||
component: RouteComponent,
|
||||
@@ -45,13 +16,7 @@ function RouteComponent() {
|
||||
// the query to retrieve the announcements
|
||||
const announcementsQuery = useQuery({
|
||||
queryKey: ["announcements"],
|
||||
queryFn: async () => {
|
||||
const response = await fetch("/api/announcements");
|
||||
const data = await response.json();
|
||||
const announcements = Announcements.parse(data);
|
||||
console.log(announcements);
|
||||
return announcements;
|
||||
},
|
||||
queryFn: getAnnouncements,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
@@ -100,56 +65,18 @@ function RouteComponent() {
|
||||
<Alert severity="error">Error (see console)</Alert>
|
||||
) : (
|
||||
<>
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell />
|
||||
<TableCell>Title</TableCell>
|
||||
<TableCell>Text</TableCell>
|
||||
<TableCell>Publication Date</TableCell>
|
||||
<TableCell />
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{announcementsQuery.data.map((a) => (
|
||||
<TableRow key={a.id}>
|
||||
<TableCell>{a.id}</TableCell>
|
||||
<TableCell>{a.title}</TableCell>
|
||||
<TableCell>
|
||||
{a.text.substring(0, 50) +
|
||||
(a.text.length > 50 ? "..." : "")}
|
||||
</TableCell>
|
||||
<TableCell>{a.publication_date.toString()}</TableCell>
|
||||
<TableCell>
|
||||
<IconButton onClick={() => openDeleteConfirmation(a)}>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<Dialog
|
||||
open={isDeleteConfirmationOpen}
|
||||
onClose={closeDeleteConfirmation}
|
||||
role="alertdialog"
|
||||
>
|
||||
<DialogTitle>Delete announcement</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
Do you want to delete the announcement{" "}
|
||||
<strong>{announcementForLatestDeleteAttempt?.title}</strong>?
|
||||
</DialogContentText>
|
||||
<DialogActions>
|
||||
<Button onClick={closeDeleteConfirmation} autoFocus>
|
||||
No
|
||||
</Button>
|
||||
<Button onClick={closeDeleteConfirmation}>Yes</Button>
|
||||
</DialogActions>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<AnnouncementTable
|
||||
announcements={announcementsQuery.data}
|
||||
openDeleteConfirmation={openDeleteConfirmation}
|
||||
/>
|
||||
{announcementForLatestDeleteAttempt && (
|
||||
<DeleteAnnouncementDialog
|
||||
announcement={announcementForLatestDeleteAttempt}
|
||||
confirmDelete={closeDeleteConfirmation}
|
||||
denyDelete={closeDeleteConfirmation}
|
||||
isDeleteConfirmationOpen={isDeleteConfirmationOpen}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import z from "zod";
|
||||
|
||||
const Announcements = z.array(
|
||||
z.object({
|
||||
id: z.number(),
|
||||
title: z.string(),
|
||||
text: z.string(),
|
||||
publication_date: z.iso.datetime().transform((arg) => new Date(arg)),
|
||||
image: z.string(),
|
||||
}),
|
||||
);
|
||||
|
||||
export type Announcement = z.infer<typeof Announcements>[0];
|
||||
|
||||
export async function getAnnouncements() {
|
||||
const response = await fetch("/api/announcements");
|
||||
const data = await response.json();
|
||||
const announcements = Announcements.parse(data);
|
||||
return announcements;
|
||||
}
|
||||
Reference in New Issue
Block a user