-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #63 from Sports-day/feature/information
お知らせ機能
- Loading branch information
Showing
7 changed files
with
378 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<Stack spacing={1} mx={2} my={3}> | ||
<Alert severity="error"> | ||
<Typography>お知らせが存在しません。</Typography> | ||
</Alert> | ||
|
||
<Button | ||
variant="contained" | ||
href="/information/" | ||
component={NextLink} | ||
> | ||
お知らせ管理に戻る | ||
</Button> | ||
</Stack> | ||
) | ||
} | ||
|
||
return ( | ||
<Stack spacing={1} mx={2} my={3}> | ||
<Breadcrumbs aria-label="breadcrumb" sx={{pl: 2}}> | ||
<Link | ||
underline="hover" | ||
color="inherit" | ||
href="/" | ||
component={NextLink} | ||
> | ||
管理者のダッシュボード | ||
</Link> | ||
<Link | ||
underline="hover" | ||
color="inherit" | ||
href={"/information/"} | ||
component={NextLink} | ||
> | ||
お知らせ管理 | ||
</Link> | ||
<Typography color="text.primary">{information.name}</Typography> | ||
</Breadcrumbs> | ||
|
||
<CardBackground title={`お知らせ`}> | ||
<InformationEditor information={information} /> | ||
</CardBackground> | ||
</Stack> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<Stack spacing={1} mx={2} my={3}> | ||
<Breadcrumbs aria-label="breadcrumb" sx={{pl: 2}}> | ||
<Link | ||
underline="hover" | ||
color="inherit" | ||
href="/" | ||
component={NextLink} | ||
> | ||
管理者のダッシュボード | ||
</Link> | ||
<Link | ||
underline="hover" | ||
color="inherit" | ||
href={"/tags/"} | ||
component={NextLink} | ||
> | ||
お知らせ管理 | ||
</Link> | ||
<Typography color="text.primary">お知らせ作成</Typography> | ||
</Breadcrumbs> | ||
<CardBackground | ||
title={"お知らせ作成"} | ||
> | ||
<InformationCreator /> | ||
</CardBackground> | ||
</Stack> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<Stack spacing={1} mx={2} my={3}> | ||
<Breadcrumbs aria-label="breadcrumb" sx={{pl: 2}}> | ||
<Link | ||
underline="hover" | ||
color="inherit" | ||
href="/" | ||
component={NextLink} | ||
> | ||
管理者のダッシュボード | ||
</Link> | ||
<Typography color="text.primary">お知らせ管理</Typography> | ||
</Breadcrumbs> | ||
<CardBackground | ||
title={"お知らせ一覧"} | ||
button={"作成"} | ||
link={"/information/create"} | ||
> | ||
<InformationAgGrid informationList={informationList}/> | ||
</CardBackground> | ||
</Stack> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<IRow[]>([]) | ||
// Column Definitions: Defines & controls grid columns. | ||
const [colDefs] = useState<ColDef<IRow>[]>([ | ||
{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<IRow>) => { | ||
const data = e.data | ||
|
||
// ignore undefined | ||
if (!data) return | ||
|
||
// redirect | ||
router.push(`/information/${data.id}`) | ||
} | ||
|
||
// Container: Defines the grid's theme & dimensions. | ||
return ( | ||
<div | ||
className={"ag-theme-quartz"} | ||
style={{ | ||
width: '100%', | ||
height: height, | ||
borderRadius: "10px" | ||
}} | ||
> | ||
<AgGridReact | ||
rowData={rowData} | ||
columnDefs={colDefs} | ||
onRowClicked={handleRowClick} | ||
/> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<TextFieldProps>(null) | ||
const contentRef = useRef<TextFieldProps>(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 ( | ||
<Stack | ||
spacing={1} | ||
> | ||
<TextField | ||
fullWidth | ||
inputRef={nameRef} | ||
label="名前" | ||
sx={{ | ||
width: "50%" | ||
}} | ||
required | ||
/> | ||
|
||
<TextField | ||
fullWidth | ||
inputRef={contentRef} | ||
label="内容" | ||
sx={{ | ||
width: "50%" | ||
}} | ||
multiline | ||
required | ||
/> | ||
|
||
|
||
<Stack | ||
direction="row" | ||
spacing={1} | ||
> | ||
<Button | ||
onClick={handleCreate} | ||
variant="contained" | ||
> | ||
作成 | ||
</Button> | ||
|
||
<Button | ||
href="/tags" | ||
component={NextLink} | ||
variant="contained" | ||
> | ||
キャンセル | ||
</Button> | ||
</Stack> | ||
</Stack> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<TextFieldProps>(null) | ||
const contentRef = useRef<TextFieldProps>(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 ( | ||
<Stack spacing={1}> | ||
<TextField | ||
label={"名前"} | ||
name={"name"} | ||
defaultValue={props.information.name} | ||
inputRef={nameRef} | ||
sx={{ | ||
width: "50%" | ||
}} | ||
/> | ||
|
||
<TextField | ||
label={"内容"} | ||
name={"content"} | ||
defaultValue={props.information.content} | ||
inputRef={contentRef} | ||
sx={{ | ||
width: "50%" | ||
}} | ||
multiline | ||
/> | ||
|
||
<Stack | ||
direction={"row"} | ||
my={0.5} | ||
spacing={1} | ||
width={"100%"} | ||
justifyContent={"space-between"} | ||
alignItems="center" | ||
> | ||
<Button | ||
variant="outlined" | ||
color={"error"} | ||
startIcon={<HiTrash/>} | ||
onClick={handleDelete} | ||
> | ||
削除 | ||
</Button> | ||
<Button | ||
variant={"contained"} | ||
onClick={handleSubmit} | ||
> | ||
保存 | ||
</Button> | ||
</Stack> | ||
</Stack> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters