Test
This commit is contained in:
74
src/App.css
74
src/App.css
@@ -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;
|
||||||
@@ -107,3 +107,71 @@ body {
|
|||||||
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;
|
||||||
|
}
|
||||||
181
src/App.js
181
src/App.js
@@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user