Skip to content

Commit

Permalink
Prepare new edit page
Browse files Browse the repository at this point in the history
  • Loading branch information
superfaz committed Sep 5, 2024
1 parent 5e63504 commit 2e7b21e
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 119 deletions.
157 changes: 69 additions & 88 deletions src/app/edit/[character]/PageContent.tsx
Original file line number Diff line number Diff line change
@@ -1,110 +1,91 @@
import clsx from "clsx";
import Link from "next/link";
import { Container, Row } from "react-bootstrap";
import Col from "react-bootstrap/Col";
import Row from "react-bootstrap/Row";
import Stack from "react-bootstrap/Stack";
import { Badge, Card } from "app/components";
import { DataSource, type IDataSource } from "data";
import { Character } from "model";
import { ViewBuilder } from "view/server";
import { Card } from "app/components";
import { CharacterDetailedView, convert } from "view/server";
import { CharacterCard } from "../PageContent";

export async function PageContent({ character }: Readonly<{ character: Character }>) {
const dataSource: IDataSource = new DataSource();
const builder = new ViewBuilder(dataSource);
function Block({
id,
code,
title,
entry,
alert,
disabled = false,
}: Readonly<{
id: string;
code: string;
title: string;
entry?: { name: string; description: string };
alert?: string;
disabled?: boolean;
}>) {
return (
<Stack direction="vertical" gap={2} data-testid={code}>
<h3 className="mt-4">{title}</h3>
<Card>
{entry && (
<Card.Body>
<Card.Title>{entry.name}</Card.Title>
<Card.Text className="text-muted">{entry.description}</Card.Text>
</Card.Body>
)}
{!entry && (
<Card.Body>
<Card.Text className="fst-italic">Aucune sélection</Card.Text>
</Card.Body>
)}
{alert && (
<Card.Body className="d-flex flex-row align-items-center text-warning-emphasis bg-warning-subtle">
<i
className="bi display-5 bi-exclamation-diamond flex-shrink-0 me-2"
role="img"
aria-label="Attention:"
></i>
<div>{alert}</div>
</Card.Body>
)}
<Card.Footer>
<Link
href={`/edit/${id}/${code}`}
className={clsx("btn btn-primary icon-link stretched-link icon-link-hover", { disabled })}
>
Configurer <i className="bi bi-chevron-right mb-1 me-auto"></i>
</Link>
</Card.Footer>
</Card>
</Stack>
);
}

export async function PageContent({ character }: Readonly<{ character: CharacterDetailedView }>) {
return (
<Stack direction="vertical" gap={2}>
<Row className="row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4">
<Col className="mt-3">
<CharacterCard character={await builder.createCharacter(character)} noAction />
<CharacterCard character={convert(character)} noAction />
</Col>
</Row>
<h3 className="mt-5">Affiliations</h3>
<Row className="row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4">
<Col className="mb-3">
<Container className="mb-2">
<Row>
<Col xs="auto" className="display-5 my-auto text-warning">
<i className="bi bi-exclamation-diamond"></i>
</Col>
<Col className="text-warning">Vous devez choisir la caractéristique principale de votre personnage.</Col>
</Row>
</Container>
<Card data-testid="race">
<Card.Header>
<Badge bg="primary">Race</Badge>
<div className="d-inline-block ms-2">Humains</div>
</Card.Header>
<Card.Body></Card.Body>
<Card.Footer className="align-items-start">
<Row>
<Col xs="auto">
<Link
href={`/edit/${character.id}/race`}
className="btn btn-primary stretched-link icon-link icon-link-hover"
>
Modifier <i className="bi bi-chevron-right mb-1 me-auto"></i>
</Link>
</Col>
<Col className="small text-muted">
Modifiez la race de votre personnage, sélectionnez une variante ou choisissez des traits alternatifs.
</Col>
</Row>
</Card.Footer>
</Card>
<Block
id={character.id}
code="race"
title="Race"
entry={character.race}
alert="Vous devez choisir la caractéristique principale de votre personnage."
/>
</Col>
<Col className="mb-3">
<Card data-testid="theme">
<Card.Header>
<Badge bg="primary">Thème</Badge>
<div className="d-inline-block ms-2">Humains</div>
</Card.Header>
<Card.Body></Card.Body>
<Card.Body>
<Row>
<Col xs="auto" className="display-5 my-auto text-warning">
<i className="bi bi-exclamation-diamond"></i>
</Col>
<Col className="text-warning">
Vous devez choisir la caractéristique principale de votre personnage.
</Col>
</Row>
</Card.Body>
<Card.Footer className="align-items-start">
<Row>
<Col xs="auto">
<Link href={`/edit/${character.id}/theme`} className="btn btn-primary stretched-link">
Modifier <i className="bi bi-chevron-right mb-1 me-auto"></i>
</Link>
</Col>
<Col className="small text-muted">
Modifiez la race de votre personnage, sélectionnez une variante ou choisissez des traits alternatifs.
</Col>
</Row>
</Card.Footer>
</Card>
<Block id={character.id} code="theme" title="Thème" entry={character.theme} disabled={!character.race} />
</Col>
<Col className="mb-3">
<Card data-testid="class">
<Card.Header>
<Badge bg="primary">Classe</Badge>
<div className="d-inline-block ms-2">Humains</div>
</Card.Header>
<Card.Body></Card.Body>
<Card.Footer className="align-items-start">
<Row>
<Col xs="auto">
<Link href={`/edit/${character.id}/class`} className="btn btn-primary stretched-link">
Modifier <i className="bi bi-chevron-right mb-1 me-auto"></i>
</Link>
</Col>
<Col className="small text-muted">
Modifiez la race de votre personnage, sélectionnez une variante ou choisissez des traits alternatifs.
</Col>
</Row>
</Card.Footer>
</Card>
<Block id={character.id} code="class" title="Classe" entry={character.class} disabled={!character.theme} />
</Col>
</Row>

<h3 className="mt-5">Détails</h3>
<h3 className="mt-5">Equipement</h3>

Expand Down
4 changes: 3 additions & 1 deletion src/app/edit/[character]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { type Metadata } from "next";
import { notFound } from "next/navigation";
import { DataSets, DataSource, type IDataSource } from "data";
import { IdSchema } from "model";
import { ViewBuilder } from "view/server";
import { isSecure } from "./helpers-server";
import { PageContent } from "./PageContent";

Expand Down Expand Up @@ -34,6 +35,7 @@ export default async function Page({ params }: Readonly<{ params: { character: s
}

// Render the page
return <PageContent character={characters[0]} />;
const builder = new ViewBuilder();
return <PageContent character={await builder.createCharacterDetailed(characters[0])} />;
}
}
18 changes: 0 additions & 18 deletions src/view/CharacterDetailedView.ts

This file was deleted.

5 changes: 0 additions & 5 deletions src/view/EntryView.ts

This file was deleted.

8 changes: 4 additions & 4 deletions src/view/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { z } from "zod";
import { IEntrySchema } from "model";
import { type IEntry, IEntrySchema } from "model";

export interface CharacterView {
id: string;
Expand All @@ -15,9 +15,9 @@ export interface CharacterDetailedView {
id: string;
name: string;
avatar?: string;
race?: string;
theme?: string;
class?: string;
race?: IEntry;
theme?: IEntry;
class?: IEntry;
level?: number;
}

Expand Down
33 changes: 33 additions & 0 deletions src/view/server/CharacterDetailedView.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { DataSets } from "data";
import type { Character } from "model";
import { CharacterDetailedView, CharacterView } from "../interfaces";
import type { ViewBuilder } from "./ViewBuilder";

import "server-only";

export async function createCharacterDetailed(this: ViewBuilder, character: Character): Promise<CharacterDetailedView> {
const race = await this.dataSource.get(DataSets.Races).findOne(character.race);
const theme = await this.dataSource.get(DataSets.Themes).findOne(character.theme);
const klass = await this.dataSource.get(DataSets.Class).findOne(character.class);
return {
id: character.id,
name: character.name,
avatar: (await this.dataSource.get(DataSets.Avatar).findOne(character.avatar))?.image,
race: race ? this.createEntry(race) : undefined,
theme: theme ? this.createEntry(theme) : undefined,
class: klass ? this.createEntry(klass) : undefined,
level: character.level,
};
}

export function convert(character: CharacterDetailedView): CharacterView {
return {
id: character.id,
name: character.name,
avatar: character.avatar,
race: character.race?.name,
theme: character.theme?.name,
class: character.class?.name,
level: character.level,
};
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DataSets } from "data";
import type { Character } from "model";
import { CharacterView } from "./interfaces";
import { CharacterView } from "../interfaces";
import type { ViewBuilder } from "./ViewBuilder";

import "server-only";
Expand Down
11 changes: 11 additions & 0 deletions src/view/server/EntryView.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IEntry, IEntrySchema } from "model";

export function createEntry<T extends IEntry>(data: T): IEntry;
export function createEntry<T extends IEntry>(data: T[]): IEntry[];
export function createEntry<T extends IEntry>(data: T[] | T): IEntry[] | IEntry {
if (!Array.isArray(data)) {
return IEntrySchema.parse(data);
} else {
return data.map((d) => IEntrySchema.parse(d));
}
}
2 changes: 1 addition & 1 deletion src/view/RaceView.ts → src/view/server/RaceView.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type Race } from "model";
import { type RaceEntry, RaceEntrySchema } from "./interfaces";
import { type RaceEntry, RaceEntrySchema } from "../interfaces";

export function createRaceEntry(data: Race[]): RaceEntry[] {
return data.map((d) => RaceEntrySchema.parse(d));
Expand Down
2 changes: 2 additions & 0 deletions src/view/ViewBuilder.ts → src/view/server/ViewBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DataSource, IDataSource } from "data";
import { createCharacterDetailed } from "./CharacterDetailedView";
import { createCharacter } from "./CharacterView";
import { createEntry } from "./EntryView";
import { createRaceEntry } from "./RaceView";
Expand All @@ -15,6 +16,7 @@ export class ViewBuilder {
}

public createCharacter = createCharacter;
public createCharacterDetailed = createCharacterDetailed;
public createEntry = createEntry;
public createRaceEntry = createRaceEntry;
}
2 changes: 1 addition & 1 deletion src/view/server.ts → src/view/server/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from "./interfaces";
export * from "../interfaces";
export * from "./RaceView";
export * from "./CharacterView";
export * from "./CharacterDetailedView";
Expand Down

0 comments on commit 2e7b21e

Please sign in to comment.