This commit is contained in:
2025-03-30 16:16:12 +00:00
parent f33d9fdf36
commit eb2fe007ab
2 changed files with 243 additions and 12 deletions

View File

@@ -14,14 +14,14 @@ body {
display: grid; display: grid;
grid-template-columns: repeat(6, 1fr); /* 4 zones in the top row */ grid-template-columns: repeat(6, 1fr); /* 4 zones in the top row */
grid-template-rows: auto auto; /* Two rows */ grid-template-rows: auto auto; /* Two rows */
gap: 20px; gap: 5px; /* Reduced gap between zones */
padding: 20px; padding: 5px;
justify-items: center; justify-items: center;
} }
.dropzone { .dropzone {
width: 200px; width: 200px;
padding: 20px; padding: 10px;
border: 2px dashed #aaa; border: 2px dashed #aaa;
background-color: #ffffff; background-color: #ffffff;
border-radius: 10px; border-radius: 10px;
@@ -106,4 +106,72 @@ body {
font-style: italic; /* Optional: make the note italic for emphasis */ font-style: italic; /* Optional: make the note italic for emphasis */
color: #555; /* Optional: subtle color for the note */ color: #555; /* Optional: subtle color for the note */
width: 100%; /* Ensure the note spans the full width of the card */ 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;
} }

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react"; import React, { useState, useEffect, useRef } from "react";
import "./App.css"; import "./App.css";
const App = () => { const App = () => {
@@ -14,8 +14,26 @@ const App = () => {
circuit: [], circuit: [],
inbound: [], inbound: [],
ppr: [], 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) => { const handleDragStart = (e, card, sourceZone) => {
e.dataTransfer.setData("card", JSON.stringify(card)); e.dataTransfer.setData("card", JSON.stringify(card));
e.dataTransfer.setData("sourceZone", sourceZone); e.dataTransfer.setData("sourceZone", sourceZone);
@@ -63,6 +81,7 @@ const App = () => {
className="card" className="card"
draggable draggable
onDragStart={(e) => handleDragStart(e, card, sourceZone)} onDragStart={(e) => handleDragStart(e, card, sourceZone)}
onClick={() => handleCardClick(card, sourceZone)}
> >
<div className="card-header"> <div className="card-header">
<span>{card.registration}</span> <span>{card.registration}</span>
@@ -75,6 +94,79 @@ const App = () => {
</div> </div>
)); ));
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 ( return (
<div className="container"> <div className="container">
{/* Top row */} {/* Top row */}
@@ -94,14 +186,6 @@ const App = () => {
<h3>Active Runway</h3> <h3>Active Runway</h3>
{renderCards(zones.runway, "runway")} {renderCards(zones.runway, "runway")}
</div> </div>
<div
className="dropzone local"
onDragOver={handleDragOver}
onDrop={(e) => handleDrop(e, "local")}
>
<h3>Local</h3>
{renderCards(zones.local, "local")}
</div>
<div <div
className="dropzone circuit" className="dropzone circuit"
onDragOver={handleDragOver} onDragOver={handleDragOver}
@@ -110,6 +194,14 @@ const App = () => {
<h3>Circuit</h3> <h3>Circuit</h3>
{renderCards(zones.circuit, "circuit")} {renderCards(zones.circuit, "circuit")}
</div> </div>
<div
className="dropzone local"
onDragOver={handleDragOver}
onDrop={(e) => handleDrop(e, "local")}
>
<h3>Local</h3>
{renderCards(zones.local, "local")}
</div>
<div <div
className="dropzone inbound" className="dropzone inbound"
onDragOver={handleDragOver} onDragOver={handleDragOver}
@@ -126,6 +218,77 @@ const App = () => {
<h3>PPRs</h3> <h3>PPRs</h3>
{renderCards(zones.ppr, "ppr")} {renderCards(zones.ppr, "ppr")}
</div> </div>
<div
className="dropzone aog"
onDragOver={handleDragOver}
onDrop={(e) => handleDrop(e, "aog")}
>
<h3>A/C on Ground</h3>
{renderCards(zones.aog, "aog")}
</div>
<div className="bottom-container">
<button onClick={() => setShowPopup(true)}>Add New Card</button>
</div>
{showPopup && (
<div className="popup">
<div className="popup-content">
<h3>{editCard ? "Edit Card" : "Add New Card"}</h3>
<label>
Registration:
<input
type="text"
name="registration"
value={newCard.registration}
onChange={handleInputChange}
ref={registrationInputRef}
onKeyDown={handleKeyDown}
/>
</label>
<label>
Type:
<input
type="text"
name="type"
value={newCard.type}
onChange={handleInputChange}
onKeyDown={handleKeyDown}
/>
</label>
<label>
POB:
<input
type="number"
name="pob"
value={newCard.pob}
onChange={handleInputChange}
onKeyDown={handleKeyDown}
/>
</label>
<label>
Note:
<input
type="text"
name="note"
value={newCard.note}
onChange={handleInputChange}
onKeyDown={handleKeyDown}
/>
</label>
<button onClick={editCard ? handleSaveEdit : handleAddCard}>
{editCard ? "Save" : "Add"}
</button>
<button
onClick={() => {
setShowPopup(false);
setEditCard(null);
setNewCard({ registration: "", type: "", pob: "", note: "" });
}}
>
Cancel
</button>
</div>
</div>
)}
</div> </div>
); );
}; };