Redesign tables arrangement layout
Some checks are pending
Build Nginx-based docker image / build-static-assets (push) Waiting to run
Some checks are pending
Build Nginx-based docker image / build-static-assets (push) Waiting to run
This commit is contained in:
parent
043b763ad7
commit
e45625e7fb
@ -6,39 +6,35 @@ import { AbstractApi } from '@/app/api/abstract-api';
|
|||||||
import { TableSimulation, TableSimulationSerializer } from '@/app/lib/tableSimulation';
|
import { TableSimulation, TableSimulationSerializer } from '@/app/lib/tableSimulation';
|
||||||
import Arrangement from '@/app/ui/arrangements/arrangement';
|
import Arrangement from '@/app/ui/arrangements/arrangement';
|
||||||
import ArrangementsTable from '@/app/ui/arrangements/arrangements-table';
|
import ArrangementsTable from '@/app/ui/arrangements/arrangements-table';
|
||||||
|
import CalculatingSummary from '@/app/ui/arrangements/calculating-summary';
|
||||||
import { classNames } from '@/app/ui/components/button';
|
import { classNames } from '@/app/ui/components/button';
|
||||||
import { Toast } from 'primereact/toast';
|
import { Toast } from 'primereact/toast';
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const toast = useRef<Toast>(null);
|
|
||||||
|
|
||||||
const show = () => {
|
|
||||||
toast.current?.show({
|
|
||||||
severity: 'success',
|
|
||||||
summary: 'Simulation created',
|
|
||||||
detail: 'Table distributions will be calculated shortly, please come back in some minutes'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const [currentArrangement, setCurrentArrangement] = useState<string | null>(null);
|
const [currentArrangement, setCurrentArrangement] = useState<string | null>(null);
|
||||||
|
|
||||||
function createSimulation() {
|
|
||||||
const api = new AbstractApi<TableSimulation>();
|
|
||||||
const serializer = new TableSimulationSerializer();
|
|
||||||
api.create(serializer, new TableSimulation(), show);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div className="flex flex-row w-full gap-4">
|
||||||
<div className="flex flex-col w-full items-center justify-between">
|
<div className="flex-1 border rounded-lg">
|
||||||
<Toast ref={toast} />
|
<ArrangementsTable onArrangementSelected={setCurrentArrangement} />
|
||||||
<button onClick={createSimulation} className={classNames('primary')}>Add new</button>
|
</div>
|
||||||
|
<div className="flex-1 border rounded-lg p-5 shadow-md">
|
||||||
|
<CalculatingSummary />
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 border rounded-lg p-5 shadow-md">
|
||||||
|
<p className="text-lg font-semibold mb-4">Inventory</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ArrangementsTable onArrangementSelected={setCurrentArrangement} />
|
<>
|
||||||
{currentArrangement && <Arrangement key={currentArrangement} id={currentArrangement} />}
|
{currentArrangement && <Arrangement key={currentArrangement} id={currentArrangement} />}
|
||||||
|
</>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -7,6 +7,8 @@ export interface Entity {
|
|||||||
id?: string;
|
id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type TableArrangementStatus = 'in_progress' | 'completed' | 'not_started';
|
||||||
|
|
||||||
export type TableArrangement = {
|
export type TableArrangement = {
|
||||||
id: string;
|
id: string;
|
||||||
number: number;
|
number: number;
|
||||||
@ -15,7 +17,7 @@ export type TableArrangement = {
|
|||||||
discomfort?: number;
|
discomfort?: number;
|
||||||
valid?: boolean;
|
valid?: boolean;
|
||||||
progress: number;
|
progress: number;
|
||||||
status: 'in_progress' | 'completed' | 'not_started';
|
status: TableArrangementStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type User = {
|
export type User = {
|
||||||
|
|||||||
@ -33,7 +33,7 @@ export class TableSimulation implements Entity {
|
|||||||
|
|
||||||
export class TableSimulationSerializer implements Serializable<TableSimulation> {
|
export class TableSimulationSerializer implements Serializable<TableSimulation> {
|
||||||
fromJson(data: any): TableSimulation {
|
fromJson(data: any): TableSimulation {
|
||||||
return new TableSimulation(data.id, data.tables.map((table: any) => {
|
return new TableSimulation(data.id, data.tables?.map((table: any) => {
|
||||||
return {
|
return {
|
||||||
number: table.number,
|
number: table.number,
|
||||||
guests: table.guests.map((guest: any) => new Guest(guest.id, guest.name, guest.color, guest.status, [], guest.group)),
|
guests: table.guests.map((guest: any) => new Guest(guest.id, guest.name, guest.color, guest.status, [], guest.group)),
|
||||||
|
|||||||
79
app/ui/arrangements/calculating-summary.tsx
Normal file
79
app/ui/arrangements/calculating-summary.tsx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/* Copyright (C) 2024-2025 LibreWeddingPlanner contributors*/
|
||||||
|
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { AbstractApi } from "@/app/api/abstract-api";
|
||||||
|
import { TableArrangementStatus } from "@/app/lib/definitions";
|
||||||
|
import { TableSimulation, TableSimulationSerializer } from "@/app/lib/tableSimulation";
|
||||||
|
import { getSlug } from "@/app/lib/utils";
|
||||||
|
import { Toast } from "primereact/toast";
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
import { ProgressSpinner } from 'primereact/progressspinner';
|
||||||
|
import { classNames } from "../components/button";
|
||||||
|
|
||||||
|
export default function CalculatingSummary() {
|
||||||
|
const [stats, setStats] = useState<{ [key in TableArrangementStatus]: number }>({
|
||||||
|
in_progress: 0,
|
||||||
|
completed: 0,
|
||||||
|
not_started: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [inProgress, setInProgress] = useState<number[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchStats = () => {
|
||||||
|
fetch(`/api/${getSlug()}/tables_arrangements/stats`)
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
setStats(data.count);
|
||||||
|
setInProgress(data.in_progress);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchStats();
|
||||||
|
const interval = setInterval(fetchStats, 10000);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const toast = useRef<Toast>(null);
|
||||||
|
|
||||||
|
function createSimulation() {
|
||||||
|
const api = new AbstractApi<TableSimulation>();
|
||||||
|
const serializer = new TableSimulationSerializer();
|
||||||
|
api.create(serializer, new TableSimulation(), () => {
|
||||||
|
toast.current?.show({
|
||||||
|
severity: 'success',
|
||||||
|
summary: 'Simulation created',
|
||||||
|
detail: 'Table distributions will be calculated shortly, please come back in some minutes'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Toast ref={toast} />
|
||||||
|
<p className="text-lg font-semibold mb-4">Processing engine</p>
|
||||||
|
<p>{stats.in_progress || 0 } processing</p>
|
||||||
|
|
||||||
|
<div className="my-4">
|
||||||
|
<div className="flex flex-row items-center gap-2">
|
||||||
|
{inProgress.map((progress, index) => (
|
||||||
|
<div key={index} className="relative size-16 flex items-center justify-center">
|
||||||
|
<ProgressSpinner className="size-16" strokeWidth="4" animationDuration={`${Math.random() * 2 + 2}s`} />
|
||||||
|
<span className="absolute text-s">
|
||||||
|
{Math.round(progress * 100)}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>+{stats.not_started || 0 } in queue</p>
|
||||||
|
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<button onClick={createSimulation} className={classNames('primary')}>Add new</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user