From f489777f3ab3b159473ba5ce08ea0346e9d15af1 Mon Sep 17 00:00:00 2001 From: testusuke Date: Tue, 8 Oct 2024 16:50:40 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E3=81=8A=E7=9F=A5=E3=82=89=E3=81=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(authenticated)/information/[id]/page.tsx | 56 ++++++++++++ .../information/create/page.tsx | 36 ++++++++ app/(authenticated)/information/page.tsx | 32 +++++++ components/information/informationAgGrid.tsx | 78 ++++++++++++++++ components/information/informationCreator.tsx | 85 ++++++++++++++++++ components/information/informationEditor.tsx | 90 +++++++++++++++++++ components/layout/navigation.tsx | 3 +- 7 files changed, 378 insertions(+), 2 deletions(-) create mode 100644 app/(authenticated)/information/[id]/page.tsx create mode 100644 app/(authenticated)/information/create/page.tsx create mode 100644 app/(authenticated)/information/page.tsx create mode 100644 components/information/informationAgGrid.tsx create mode 100644 components/information/informationCreator.tsx create mode 100644 components/information/informationEditor.tsx diff --git a/app/(authenticated)/information/[id]/page.tsx b/app/(authenticated)/information/[id]/page.tsx new file mode 100644 index 0000000..c98bd4a --- /dev/null +++ b/app/(authenticated)/information/[id]/page.tsx @@ -0,0 +1,56 @@ +import {Alert, Breadcrumbs, Button, Link, Stack, Typography} from "@mui/material"; +import CardBackground from "@/components/layout/cardBackground"; +import NextLink from "next/link"; +import {informationFactory} from "@/src/models/InformationModel"; +import InformationEditor from "@/components/information/informationEditor"; + +export default async function InformationDetailPage({params}: { params: { id: string } }) { + const informationId = parseInt(params.id, 10) + const information = await informationFactory().show(informationId) + + if (isNaN(informationId) || !information) { + return ( + + + お知らせが存在しません。 + + + + + ) + } + + return ( + + + + 管理者のダッシュボード + + + お知らせ管理 + + {information.name} + + + + + + + ) +} diff --git a/app/(authenticated)/information/create/page.tsx b/app/(authenticated)/information/create/page.tsx new file mode 100644 index 0000000..c78032e --- /dev/null +++ b/app/(authenticated)/information/create/page.tsx @@ -0,0 +1,36 @@ +import {Stack, Breadcrumbs, Link, Typography} from "@mui/material"; +import CardBackground from "@/components/layout/cardBackground"; +import NextLink from "next/link"; +import InformationCreator from "@/components/information/informationCreator"; + +export default function InformationCreatePage() { + + return ( + + + + 管理者のダッシュボード + + + お知らせ管理 + + お知らせ作成 + + + + + + ); +} diff --git a/app/(authenticated)/information/page.tsx b/app/(authenticated)/information/page.tsx new file mode 100644 index 0000000..b36fcef --- /dev/null +++ b/app/(authenticated)/information/page.tsx @@ -0,0 +1,32 @@ +import {Stack, Breadcrumbs, Link, Typography} from "@mui/material"; +import CardBackground from "@/components/layout/cardBackground"; +import NextLink from "next/link"; +import {informationFactory} from "@/src/models/InformationModel"; +import InformationAgGrid from "@/components/information/informationAgGrid"; + +export default async function TagsPage() { + const informationList = await informationFactory().index() + + return ( + + + + 管理者のダッシュボード + + お知らせ管理 + + + + + + ); +} diff --git a/components/information/informationAgGrid.tsx b/components/information/informationAgGrid.tsx new file mode 100644 index 0000000..837de27 --- /dev/null +++ b/components/information/informationAgGrid.tsx @@ -0,0 +1,78 @@ +'use client' +import {useEffect, useState} from 'react'; +import {AgGridReact} from 'ag-grid-react'; +import "ag-grid-community/styles/ag-grid.css"; // Mandatory CSS required by the grid +import "ag-grid-community/styles/ag-theme-quartz.css"; // Optional Theme applied to the grid + +import {ColDef, ModuleRegistry, RowClickedEvent} from 'ag-grid-community'; +import {ClientSideRowModelModule} from 'ag-grid-community'; +import {useRouter} from "next/navigation"; +import {Information} from "@/src/models/InformationModel"; + +ModuleRegistry.registerModules([ClientSideRowModelModule]); + +export type InformationAgGridProps = { + informationList: Information[] +} + +// Row Data Interface +type IRow = { + id: number, + name: string, + content: string, +} + +// Create new GridExample component +export default function InformationAgGrid(props: InformationAgGridProps) { + const height = 'calc(100vh - 230px)'; + const router = useRouter() + // Row Data: The data to be displayed. + const [rowData, setRowData] = useState([]) + // Column Definitions: Defines & controls grid columns. + const [colDefs] = useState[]>([ + {field: "id", headerName: "ID"}, + {field: "name", headerName: "名前"}, + {field: "content", headerName: "内容"}, + ]); + + useEffect(() => { + const informationList = props.informationList.map((information): IRow => { + return { + id: information.id, + name: information.name, + content: information.content + } + }) + + // set row data + setRowData(informationList) + }, [props.informationList]) + + const handleRowClick = (e: RowClickedEvent) => { + const data = e.data + + // ignore undefined + if (!data) return + + // redirect + router.push(`/information/${data.id}`) + } + + // Container: Defines the grid's theme & dimensions. + return ( +
+ +
+ ); +} \ No newline at end of file diff --git a/components/information/informationCreator.tsx b/components/information/informationCreator.tsx new file mode 100644 index 0000000..7b28561 --- /dev/null +++ b/components/information/informationCreator.tsx @@ -0,0 +1,85 @@ +'use client' +import {Button, Stack, TextField, TextFieldProps} from "@mui/material"; +import {useRouter} from "next/navigation"; +import {useRef} from "react"; +import NextLink from "next/link"; +import {informationFactory} from "@/src/models/InformationModel"; + +export default function InformationCreator() { + const router = useRouter() + const nameRef = useRef(null) + const contentRef = useRef(null) + + const handleCreate = async () => { + // create role + const name = nameRef.current?.value as string + const content = contentRef.current?.value as string + + + if (!name) { + alert("名前を入力してください") + return + } + + if (!content) { + alert("内容を入力してください") + return + } + + await informationFactory().create({ + name: name, + content: content + }) + + // redirect to role page + router.push('/information') + } + + return ( + + + + + + + + + + + + + ) +} diff --git a/components/information/informationEditor.tsx b/components/information/informationEditor.tsx new file mode 100644 index 0000000..641bbe2 --- /dev/null +++ b/components/information/informationEditor.tsx @@ -0,0 +1,90 @@ +'use client' +import React, {useRef} from "react"; +import { + Button, + Stack, + TextField, + TextFieldProps +} from "@mui/material"; +import {useRouter} from "next/navigation"; +import {Information, informationFactory} from "@/src/models/InformationModel"; +import {HiTrash} from "react-icons/hi2"; + +export type InformationEditorProps = { + information: Information +} + +export default function InformationEditor(props: InformationEditorProps) { + const router = useRouter() + const nameRef = useRef(null) + const contentRef = useRef(null) + + const handleSubmit = async () => { + const name = nameRef.current?.value as string + const content = contentRef.current?.value as string + + await informationFactory().update(props.information.id, { + name: name, + content: content, + }) + + // reload + router.push("/information") + } + + const handleDelete = async () => { + await informationFactory().delete(props.information.id) + + // reload + router.push("/information") + } + + return ( + + + + + + + + + + + ) +} diff --git a/components/layout/navigation.tsx b/components/layout/navigation.tsx index 9898c68..c18cfc1 100644 --- a/components/layout/navigation.tsx +++ b/components/layout/navigation.tsx @@ -62,11 +62,10 @@ export const Navigation = () => {