From 28a50996239820ba61dc018e24ff19877e5be924 Mon Sep 17 00:00:00 2001 From: Alexey Suprun Date: Sun, 19 Jan 2025 16:48:46 +0100 Subject: [PATCH] feat: add modals to simulation forms page --- app/components/ParametersForm/index.test.tsx | 16 +-- app/components/ParametersForm/index.tsx | 129 +++++++++++-------- app/components/SimulationForms/index.tsx | 37 +++++- app/ui-lib/Modal/index.tsx | 2 +- 4 files changed, 112 insertions(+), 72 deletions(-) diff --git a/app/components/ParametersForm/index.test.tsx b/app/components/ParametersForm/index.test.tsx index 1f0604d..b6eadb0 100644 --- a/app/components/ParametersForm/index.test.tsx +++ b/app/components/ParametersForm/index.test.tsx @@ -1,14 +1,7 @@ -import { useRouter } from 'next/navigation'; -import { Mock } from 'vitest'; import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import ParametersForm from '.'; -vi.mock('next/navigation', () => ({ - useRouter: vi.fn(), -})); - describe('ParametersForm Component', () => { - const mockPush = vi.fn(); const mockConfiguration = { isFieldFocused: false, stations: [ @@ -19,7 +12,7 @@ describe('ParametersForm Component', () => { }; beforeEach(() => { - (useRouter as Mock).mockReturnValue({ push: mockPush }); + HTMLDialogElement.prototype.showModal = vi.fn(); vi.clearAllMocks(); sessionStorage.clear(); }); @@ -30,7 +23,7 @@ describe('ParametersForm Component', () => { expect(screen.getByLabelText(/Select Stations Configuration/i)).toBeInTheDocument(); expect(screen.getByLabelText(/Car Consumption \(kWh\)/i)).toBeInTheDocument(); expect(screen.getByLabelText(/Arrival Probability Multiplier/i)).toBeInTheDocument(); - expect(screen.getByRole('button', { name: /Prepare Simulation/i })).toBeDisabled(); + expect(screen.getByRole('button', { name: /Prepare Report/i })).toBeDisabled(); }); it('allows valid input, enables the submit button, and navigates on click', async () => { @@ -48,7 +41,7 @@ describe('ParametersForm Component', () => { target: { value: '100' }, }); - const submitButton = screen.getByRole('button', { name: /Prepare Simulation/i }); + const submitButton = screen.getByRole('button', { name: /Prepare Report/i }); await waitFor(() => { expect(submitButton).toBeEnabled(); }); @@ -62,7 +55,6 @@ describe('ParametersForm Component', () => { arrivalProbability: 100, configuredStations: JSON.stringify({ chargingPower: '11', count: 5 }), }); - expect(mockPush).toHaveBeenCalledWith('/simulation/results'); }); }); @@ -73,7 +65,7 @@ describe('ParametersForm Component', () => { target: { value: '4' }, }); - fireEvent.click(screen.getByRole('button', { name: /Prepare Simulation/i })); + fireEvent.click(screen.getByRole('button', { name: /Prepare Report/i })); await waitFor(() => { expect( diff --git a/app/components/ParametersForm/index.tsx b/app/components/ParametersForm/index.tsx index 6d4d0e4..4905a7b 100644 --- a/app/components/ParametersForm/index.tsx +++ b/app/components/ParametersForm/index.tsx @@ -1,11 +1,11 @@ 'use client'; -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; +import Link from 'next/link'; import { useForm } from 'react-hook-form'; -import { useRouter } from 'next/navigation'; import { zodResolver } from '@hookform/resolvers/zod'; import { ParametersFormData, parametersFormSchema } from '@/app/formSchemas'; -import { Form, FormInput } from '@/app/ui-lib'; +import { Form, FormInput, Modal } from '@/app/ui-lib'; import { SIMULATION_RESULTS_URL } from '@/app/constants'; export default function ParametersForm({ @@ -16,7 +16,7 @@ export default function ParametersForm({ stations: { chargingPower: string; count: number }[]; }; }) { - const router = useRouter(); + const simulationModalRef = useRef(null); const { register, @@ -36,64 +36,83 @@ export default function ParametersForm({ const onSubmit = async (data: ParametersFormData) => { sessionStorage.setItem('simulationParams', JSON.stringify(data)); - router.push(SIMULATION_RESULTS_URL); + if (simulationModalRef.current) { + simulationModalRef.current.showModal(); + } }; return ( -
-

Simulation Parameters

-

- Use this form to configure the global simulation settings, including the number of arriving - vehicles, their energy consumption, and the overall behavior of the charging stations. - Adjust these parameters to match real-world scenarios and optimize your infrastructure - planning. -

-
-
- ({ - value: JSON.stringify(station), - label: `${station.count} x ${station.chargingPower} kW`, - }))} - /> + <> + +

Simulation Parameters

+

+ Use this form to configure the global simulation settings, including the number of + arriving vehicles, their energy consumption, and the overall behavior of the charging + stations. Adjust these parameters to match real-world scenarios and optimize your + infrastructure planning. +

+
+
+ ({ + value: JSON.stringify(station), + label: `${station.count} x ${station.chargingPower} kW`, + }))} + /> +
+
+ +
+
-
+
-
-
-
- -
- - + + + +
+
+

Simulation Report is Ready

+

Your simulation report was successfully generated.

+ + + Check the report + +
+
+
+ ); } diff --git a/app/components/SimulationForms/index.tsx b/app/components/SimulationForms/index.tsx index 60e64b2..f340197 100644 --- a/app/components/SimulationForms/index.tsx +++ b/app/components/SimulationForms/index.tsx @@ -1,10 +1,14 @@ 'use client'; -import { useState } from 'react'; +import { useRef, useState } from 'react'; import SimulationParametersForm from '@/app/components/ParametersForm'; import ChargeStationsForm from '@/app/components/ChargeStationsForm'; +import { Modal } from '@/app/ui-lib'; export default function SimulationPage() { + const [showDuplicateModal, setShowDuplicateModal] = useState(false); + const addStationModalRef = useRef(null); + const [stationsConfiguration, setStationsConfiguration] = useState({ isFieldFocused: false, stations: [ @@ -16,13 +20,18 @@ export default function SimulationPage() { const addStation = (newStation: { chargingPower: string; count: number }) => { setStationsConfiguration((prev) => { - const isDuplicate = prev.stations.some( + const isStationDuplicate = prev.stations.some( (station) => station.chargingPower === newStation.chargingPower && station.count === newStation.count, ); - if (isDuplicate) { - alert('This station configuration already exists!'); + setShowDuplicateModal(isStationDuplicate); + + if (addStationModalRef.current) { + addStationModalRef.current.showModal(); + } + + if (isStationDuplicate) { return prev; } @@ -38,6 +47,26 @@ export default function SimulationPage() {
+ +
+ {showDuplicateModal ? ( +
+

Configuration already exists

+

Please try to add another combination.

+
+ ) : ( +
+

A new configuration was added

+

+ A new configuration was added to +
+ the "Select Stations Configuration" field. +

+
+ )} +
+
+ ;
); } diff --git a/app/ui-lib/Modal/index.tsx b/app/ui-lib/Modal/index.tsx index 2331662..241a8b9 100644 --- a/app/ui-lib/Modal/index.tsx +++ b/app/ui-lib/Modal/index.tsx @@ -9,7 +9,7 @@ function Modal({ }) { return ( -
+