Skip to content

Commit 0ff77e1

Browse files
committed
Update PDCModal.tsx
1 parent cb6919b commit 0ff77e1

File tree

1 file changed

+91
-30
lines changed

1 file changed

+91
-30
lines changed

src/components/tools/PDCModal.tsx

Lines changed: 91 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,30 +32,31 @@ const PDCModal: React.FC<PDCModalProps> = ({ isOpen, onClose, flight, onIssuePDC
3232
'standard'
3333
);
3434
const [error, setError] = useState<string | null>(null);
35+
const [customRemarks, setCustomRemarks] = useState<string>('');
3536

3637
const generateRandomSquawk = (): string => {
3738
return Array.from({ length: 4 }, () =>
3839
Math.floor(Math.random() * 8)
3940
).join('');
4041
};
4142

42-
const generateRandomIdentifier = (): string => {
43-
const squawk = getSquawk();
43+
const [autoSquawk] = useState(() => generateRandomSquawk());
44+
45+
const [autoIdentifier] = useState(() => {
46+
// Generate identifier from squawk and callsign
47+
const squawk = flight?.squawk || autoSquawk;
4448
const firstThreeNumbers = squawk.substring(0, 3);
45-
49+
4650
let firstLetter = 'A';
4751
if (flight?.callsign) {
4852
const letters = flight.callsign.match(/[A-Z]/i);
4953
if (letters && letters.length > 0) {
5054
firstLetter = letters[0].toUpperCase();
5155
}
5256
}
53-
54-
return firstThreeNumbers + firstLetter;
55-
};
5657

57-
const [autoSquawk] = useState(() => generateRandomSquawk());
58-
const [autoIdentifier] = useState(() => generateRandomIdentifier());
58+
return firstThreeNumbers + firstLetter;
59+
});
5960

6061
useEffect(() => {
6162
localStorage.setItem(
@@ -70,6 +71,32 @@ const PDCModal: React.FC<PDCModalProps> = ({ isOpen, onClose, flight, onIssuePDC
7071
}
7172
}, [isOpen, flight]);
7273

74+
// Pre-fill remarks with default text when modal opens
75+
useEffect(() => {
76+
if (isOpen && flight) {
77+
const sidText = flight.sid || 'DCT';
78+
const isVFR = flight.flight_type === 'VFR';
79+
const isRadarVectors = sidText === 'RADAR VECTORS';
80+
const clearedAlt = flight.clearedFL || '030';
81+
const freqs = getFrequencies();
82+
83+
let climbInstruction;
84+
if (isVFR || isRadarVectors) {
85+
climbInstruction = `CLEARED ${sidText}`;
86+
} else {
87+
climbInstruction = `CLEARED ${sidText} DEPARTURE CLIMB VIA SID`;
88+
}
89+
90+
const defaultRemarks = `${climbInstruction} EXP ${flight.cruisingFL || clearedAlt} 10 MIN AFT DP`;
91+
setCustomRemarks(defaultRemarks);
92+
}
93+
94+
// Reset remarks when modal closes
95+
if (!isOpen) {
96+
setCustomRemarks('');
97+
}
98+
}, [isOpen, flight]);
99+
73100
const fetchAirportFrequencies = async (icao: string) => {
74101
if (!icao) return;
75102

@@ -141,9 +168,14 @@ const PDCModal: React.FC<PDCModalProps> = ({ isOpen, onClose, flight, onIssuePDC
141168
departure: customFreqs.departure || '122.800'
142169
};
143170
}
171+
172+
173+
const clearanceFreq = airportFreqs.clearanceDelivery || airportFreqs.ground || '122.800';
174+
const departureFreq = airportFreqs.departure || airportFreqs.tower || '122.800';
175+
144176
return {
145-
clearance: airportFreqs.clearanceDelivery || '122.800',
146-
departure: airportFreqs.departure || '122.800'
177+
clearance: clearanceFreq,
178+
departure: departureFreq
147179
};
148180
};
149181

@@ -156,23 +188,15 @@ const PDCModal: React.FC<PDCModalProps> = ({ isOpen, onClose, flight, onIssuePDC
156188
const sidText = flight.sid || 'DCT';
157189
const freqs = getFrequencies();
158190
const clearedAlt = flight.clearedFL || '030';
159-
const isVFR = flight.flight_type === 'VFR';
160-
const isRadarVectors = sidText === 'RADAR VECTORS';
161-
162-
let climbInstruction;
163-
if (isVFR || isRadarVectors) {
164-
climbInstruction = `CLEARED ${sidText}`;
165-
} else {
166-
climbInstruction = `CLEARED ${sidText} DEPARTURE CLIMB VIA SID`;
167-
}
168191

169192
if (pdcFormat === 'simplified') {
170193
return `PDC FOR ${flight.callsign}
171194
CLEARED TO ${flight.arrival} VIA ${sidText}
172195
CLIMB AND MAINTAIN ${clearedAlt}
173196
SQUAWK ${squawk}
174-
CONTACT DEPARTURE ${freqs.departure}
175-
CONTACT CLEARANCE ${freqs.clearance} TO PUSH`;
197+
DEPARTURE ${freqs.departure}
198+
CLEARANCE ${freqs.clearance}
199+
IDENTIFIER ${identifier}${customRemarks ? `\nREMARKS: ${customRemarks}` : ''}`;
176200
}
177201

178202
return `ACARS: PDC | CALLSIGN: ${
@@ -181,19 +205,29 @@ CONTACT CLEARANCE ${freqs.clearance} TO PUSH`;
181205
DEPARTURE: ${flight.departure} | DESTINATION: ${flight.arrival} |
182206
ROUTE: ${flight.departure}.${sidText}..${flight.arrival} |
183207
ALTITUDE: ${clearedAlt} | TRANSPONDER: ${squawk} | REMARKS:
184-
${climbInstruction} EXP ${flight.cruisingFL || clearedAlt} 10
185-
MIN AFT DP DPFRQ ${freqs.departure} | CTC ${freqs.clearance} TO PUSH
208+
${customRemarks}, DPFRQ ${freqs.departure} CTC ${freqs.clearance} TO PUSH
186209
IDENTIFIER: ${identifier}`;
187210
};
188211

189212
const handleCustomFreqChange = (
190213
type: keyof AirportFrequencies,
191214
value: string
192215
) => {
193-
setCustomFreqs((prev) => ({ ...prev, [type]: value }));
216+
const filtered = value.replace(/[^0-9.]/g, '');
217+
setCustomFreqs((prev) => ({ ...prev, [type]: filtered }));
194218
setUseCustomFreqs(true);
195219
};
196220

221+
const handleSquawkChange = (value: string) => {
222+
const filtered = value.replace(/[^0-7]/g, '').slice(0, 4);
223+
setCustomSquawk(filtered);
224+
};
225+
226+
const handleIdentifierChange = (value: string) => {
227+
const filtered = value.replace(/[^A-Z0-9]/gi, '').slice(0, 4).toUpperCase();
228+
setCustomIdentifier(filtered);
229+
};
230+
197231
const copyToClipboard = async () => {
198232
if (!flight) return;
199233

@@ -366,6 +400,24 @@ IDENTIFIER: ${identifier}`;
366400
</div>
367401
</div>
368402
</div>
403+
{/* Remarks */}
404+
<div className="space-y-3">
405+
<h3 className="text-lg font-semibold text-blue-300">
406+
Remarks
407+
</h3>
408+
<div>
409+
<textarea
410+
value={customRemarks}
411+
onChange={(e) => setCustomRemarks(e.target.value)}
412+
placeholder="Enter PDC remarks..."
413+
className="w-full bg-zinc-800 border border-zinc-700 text-white rounded-lg p-3 font-mono text-sm min-h-[80px] resize-y focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
414+
maxLength={250}
415+
/>
416+
<p className="text-xs text-gray-500 mt-1">
417+
Edit Remarks
418+
</p>
419+
</div>
420+
</div>
369421

370422
{/* Frequencies */}
371423
<div className="space-y-3">
@@ -392,9 +444,9 @@ IDENTIFIER: ${identifier}`;
392444
value={
393445
useCustomFreqs
394446
? customFreqs.clearanceDelivery ||
395-
''
447+
''
396448
: airportFreqs.clearanceDelivery ||
397-
'122.800'
449+
'122.800'
398450
}
399451
onChange={(value) =>
400452
handleCustomFreqChange(
@@ -416,7 +468,7 @@ IDENTIFIER: ${identifier}`;
416468
useCustomFreqs
417469
? customFreqs.departure || ''
418470
: airportFreqs.departure ||
419-
'122.800'
471+
'122.800'
420472
}
421473
onChange={(value) =>
422474
handleCustomFreqChange(
@@ -462,12 +514,17 @@ IDENTIFIER: ${identifier}`;
462514
? customSquawk
463515
: flight.squawk || autoSquawk
464516
}
465-
onChange={setCustomSquawk}
517+
onChange={handleSquawkChange}
466518
placeholder="e.g. 1234"
467519
className="w-full bg-zinc-800 border border-zinc-700 font-mono"
468520
maxLength={4}
469521
disabled={!useCustomSquawk}
470522
/>
523+
{useCustomSquawk && (
524+
<p className="text-xs text-gray-500 mt-1">
525+
Only digits 0-7 allowed
526+
</p>
527+
)}
471528
</div>
472529
<div>
473530
<div className="flex items-center justify-between mb-2">
@@ -497,16 +554,20 @@ IDENTIFIER: ${identifier}`;
497554
? customIdentifier
498555
: autoIdentifier
499556
}
500-
onChange={setCustomIdentifier}
557+
onChange={handleIdentifierChange}
501558
placeholder="e.g. AB12"
502559
className="w-full bg-zinc-800 border border-zinc-700 font-mono"
503560
maxLength={4}
504561
disabled={!useCustomIdentifier}
505562
/>
563+
{useCustomIdentifier && (
564+
<p className="text-xs text-gray-500 mt-1">
565+
Letters and numbers only
566+
</p>
567+
)}
506568
</div>
507569
</div>
508570
</div>
509-
510571
{/* Warning */}
511572
<div className="bg-amber-900/20 p-3 rounded-lg border border-amber-700 text-amber-300 text-xs">
512573
<div className="flex items-start">

0 commit comments

Comments
 (0)