From eb2fe007ab86da26e2a923e7111922ccdcaa136f Mon Sep 17 00:00:00 2001 From: James Pattinson Date: Sun, 30 Mar 2025 16:16:12 +0000 Subject: [PATCH] Test --- src/App.css | 74 ++++++++++++++++++++- src/App.js | 181 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 243 insertions(+), 12 deletions(-) diff --git a/src/App.css b/src/App.css index 54c0c8d..94b33cb 100644 --- a/src/App.css +++ b/src/App.css @@ -14,14 +14,14 @@ body { display: grid; grid-template-columns: repeat(6, 1fr); /* 4 zones in the top row */ grid-template-rows: auto auto; /* Two rows */ - gap: 20px; - padding: 20px; + gap: 5px; /* Reduced gap between zones */ + padding: 5px; justify-items: center; } .dropzone { width: 200px; - padding: 20px; + padding: 10px; border: 2px dashed #aaa; background-color: #ffffff; border-radius: 10px; @@ -106,4 +106,72 @@ body { font-style: italic; /* Optional: make the note italic for emphasis */ color: #555; /* Optional: subtle color for the note */ width: 100%; /* Ensure the note spans the full width of the card */ + } + + .popup { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */ + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; /* Ensure it appears above other elements */ + } + + .popup-content { + background-color: #ffffff; + padding: 20px; + border-radius: 10px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + width: 300px; + max-width: 90%; + text-align: center; + } + + .popup-content h3 { + margin-bottom: 20px; + color: #333; + } + + .popup-content label { + display: block; + margin-bottom: 10px; + text-align: left; + font-weight: bold; + color: #555; + } + + .popup-content input { + width: 100%; + padding: 8px; + margin-bottom: 15px; + border: 1px solid #ccc; + border-radius: 5px; + box-sizing: border-box; + } + + .popup-content button { + padding: 10px 20px; + margin: 5px; + border: none; + border-radius: 5px; + cursor: pointer; + font-size: 1em; + } + + .popup-content button:first-of-type { + background-color: #4caf50; /* Green for Add */ + color: white; + } + + .popup-content button:last-of-type { + background-color: #f44336; /* Red for Cancel */ + color: white; + } + + .popup-content button:hover { + opacity: 0.9; } \ No newline at end of file diff --git a/src/App.js b/src/App.js index f80257a..dfead02 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useEffect, useRef } from "react"; import "./App.css"; const App = () => { @@ -14,8 +14,26 @@ const App = () => { circuit: [], inbound: [], ppr: [], + aog: [], }); + const [showPopup, setShowPopup] = useState(false); + const [newCard, setNewCard] = useState({ + registration: "", + type: "", + pob: "", + note: "", + }); + const [editCard, setEditCard] = useState(null); + + const registrationInputRef = useRef(null); + + useEffect(() => { + if (showPopup) { + registrationInputRef.current?.focus(); + } + }, [showPopup]); + const handleDragStart = (e, card, sourceZone) => { e.dataTransfer.setData("card", JSON.stringify(card)); e.dataTransfer.setData("sourceZone", sourceZone); @@ -63,6 +81,7 @@ const App = () => { className="card" draggable onDragStart={(e) => handleDragStart(e, card, sourceZone)} + onClick={() => handleCardClick(card, sourceZone)} >
{card.registration} @@ -75,6 +94,79 @@ const App = () => {
)); + const handleInputChange = (e) => { + const { name, value } = e.target; + setNewCard((prev) => ({ + ...prev, + [name]: name === "registration" ? value.toUpperCase() : value, + })); + }; + + const handleAddCard = () => { + if ( + !newCard.registration || + !newCard.type || + isNaN(parseInt(newCard.pob, 10)) + ) { + alert("All fields are required and POB must be a number."); + return; + } + + const card = { + id: Date.now().toString(), + registration: newCard.registration, + type: newCard.type, + pob: parseInt(newCard.pob, 10), + note: newCard.note, + }; + + setZones((prevZones) => ({ + ...prevZones, + awaitingDepart: [...prevZones.awaitingDepart, card], + })); + + setShowPopup(false); + setNewCard({ registration: "", type: "", pob: "", note: "" }); + }; + + const handleCardClick = (card, sourceZone) => { + setEditCard({ ...card, sourceZone }); + setNewCard(card); + setShowPopup(true); + }; + + const handleSaveEdit = () => { + if ( + !newCard.registration || + !newCard.type || + isNaN(parseInt(newCard.pob, 10)) + ) { + alert("All fields are required and POB must be a number."); + return; + } + + setZones((prevZones) => { + const updatedSourceZone = prevZones[editCard.sourceZone].map((item) => + item.id === editCard.id ? { ...newCard, id: editCard.id } : item + ); + + return { + ...prevZones, + [editCard.sourceZone]: updatedSourceZone, + }; + }); + + setShowPopup(false); + setEditCard(null); + setNewCard({ registration: "", type: "", pob: "", note: "" }); + }; + + const handleKeyDown = (e) => { + if (e.key === "Enter") { + editCard ? handleSaveEdit() : handleAddCard(); + } + }; + return (
{/* Top row */} @@ -94,14 +186,6 @@ const App = () => {

Active Runway

{renderCards(zones.runway, "runway")}
-
handleDrop(e, "local")} - > -

Local

- {renderCards(zones.local, "local")} -
{

Circuit

{renderCards(zones.circuit, "circuit")}
+
handleDrop(e, "local")} + > +

Local

+ {renderCards(zones.local, "local")} +
{

PPRs

{renderCards(zones.ppr, "ppr")}
+
handleDrop(e, "aog")} + > +

A/C on Ground

+ {renderCards(zones.aog, "aog")} +
+
+ +
+ {showPopup && ( +
+
+

{editCard ? "Edit Card" : "Add New Card"}

+ + + + + + +
+
+ )} ); };