Drone and PPR and operational updates

This commit is contained in:
2026-06-20 05:31:04 -04:00
parent b8d7cdddcd
commit 3e8b3cf4c1
15 changed files with 1727 additions and 39 deletions
+4
View File
@@ -23,6 +23,10 @@ import BaseLayout from '../../layouts/BaseLayout.astro';
much notice as possible via email, with the following information:
</p>
<p>
<a class="button primary" href="/drone-flight-request/">Request a Drone Flight</a>
</p>
<ul>
<li>Date of flight</li>
<li>Estimated take-off time</li>
+239
View File
@@ -0,0 +1,239 @@
---
import BaseLayout from '../../layouts/BaseLayout.astro';
const gaCharges = [
['Microlight', '£10', 'Free of charge', '£10', '£20'],
['Standard GA Single', '£15', 'Free of charge', '£15', '£30'],
['GA Light Twin', '£25', 'Free of charge', '£15', '£30'],
['2500kg - 3000kg', '£60', 'Free of charge', '£30', 'Price on request'],
['3001kg - 4000kg', '£80', '5 hours free, £5 after', '£45', 'Price on request'],
['4001kg - 5000kg', '£180', '5 hours free, £10 after', '£60', 'Price on request'],
];
const touchAndGoCharges = [
['Microlight', '£5', '£10'],
['Standard GA Single', '£10', '£30'],
['GA Light Twin', '£15', '£50'],
['2500kg - 3000kg', '£30', '£120'],
['3001kg - 4000kg', '£40', '£160'],
['4001kg - 5000kg', '£80', '£360'],
];
const businessCharges = [
['4001kg - 5000kg', '£200', '5 hours free, £15 after', '£80'],
['5001kg - 6000kg', '£220', '5 hours free, £15 after', '£80'],
['6001kg - 7000kg', '£240', '5 hours free, £15 after', '£80'],
['7001kg - 8000kg', '£265', '4 hours free, £15 after', '£80'],
['8001kg - 9000kg', '£290', '4 hours free, £20 after', '£100'],
['9001kg - 10000kg', '£330', '4 hours free, £20 after', '£100'],
['10001kg - 11000kg', '£360', '£20', '£120'],
['11001kg - 12000kg', '£390', '£20', '£120'],
['12001kg - 13000kg', '£420', '£25', '£140'],
['13001kg - 14000kg', '£450', '£25', '£140'],
['14001kg - 15000kg', '£480', '£25', '£140'],
['15001kg - 16000kg', '£560', '£30', '£180'],
['16001kg - 17000kg', '£640', '£30', '£180'],
['17001kg - 18000kg', '£740', '£30', '£180'],
];
const additionalCharges = [
['Handling charges', 'Up to £60, price on request', 'Includes marshalling, catering, hotel and transport organisation, and use of crew room if available.'],
['Out of hours', '£130', 'Per hour required.'],
['Passenger loading', '£5 per passenger', 'Aircraft up to 5000kg.'],
['Passenger loading', '£8 per passenger', 'Aircraft between 5001kg and 10000kg.'],
['Passenger loading', '£10 per passenger', 'Aircraft 10001kg and above.'],
['Porterage charges', 'On request', 'Assistance with baggage or cargo from or to the aircraft.'],
['Runway closure', '£50', 'At management discretion following incident or accident.'],
['Drones', '£25', 'Commercial drones need 2 days notice before flight and a permit.'],
];
---
<BaseLayout title="Fees and Charges" description="Swansea Airport landing, parking, handling, and related charges.">
<section class="container fees-page">
<p class="eyebrow">About</p>
<h1 class="section-title">Fees and Charges</h1>
<p class="section-copy">Prices are based on maximum take-off weight (MTOW) unless otherwise stated.</p>
<section class="fee-section">
<h2>General Aviation</h2>
<div class="fee-table-wrap">
<table class="fee-table">
<thead>
<tr>
<th scope="col">Type</th>
<th scope="col">Landing fee</th>
<th scope="col">Daytime parking</th>
<th scope="col">Overnight parking outside</th>
<th scope="col">Overnight parking hangar</th>
</tr>
</thead>
<tbody>
{gaCharges.map((row) => (
<tr>
{row.map((cell) => <td>{cell}</td>)}
</tr>
))}
</tbody>
</table>
</div>
</section>
<section class="fee-section">
<h2>Touch and Go's</h2>
<div class="fee-table-wrap compact">
<table class="fee-table">
<thead>
<tr>
<th scope="col">Type</th>
<th scope="col">Single</th>
<th scope="col">Unlimited</th>
</tr>
</thead>
<tbody>
{touchAndGoCharges.map((row) => (
<tr>
{row.map((cell) => <td>{cell}</td>)}
</tr>
))}
</tbody>
</table>
</div>
</section>
<section class="fee-section">
<h2>GA Notes</h2>
<ul>
<li>Hangarage parking is subject to availability.</li>
<li>Daytime parking is 0900-1700 local.</li>
<li>Overnight parking is 1700-0900 local.</li>
<li>GA aircraft departing after hours will not be subject to additional fees.</li>
<li>Handling is free of charge up to 2500kg.</li>
<li>Aircraft above 2500kg in the GA category may be charged up to £60 for handling.</li>
<li>Other prices are by request.</li>
</ul>
</section>
<section class="fee-section">
<h2>Business and Corporate Aviation</h2>
<div class="fee-table-wrap">
<table class="fee-table">
<thead>
<tr>
<th scope="col">MTOW</th>
<th scope="col">Landing fee</th>
<th scope="col">Daytime parking</th>
<th scope="col">Overnight parking</th>
</tr>
</thead>
<tbody>
{businessCharges.map((row) => (
<tr>
{row.map((cell) => <td>{cell}</td>)}
</tr>
))}
</tbody>
</table>
</div>
<ul>
<li>Hangarage parking is subject to availability.</li>
<li>Daytime parking is 0900-1700 local.</li>
<li>Overnight parking is 1700-0900 local.</li>
<li>Aircraft departing out of hours will be charged £130 per hour.</li>
<li>Aircraft may be charged for handling services.</li>
</ul>
</section>
<section class="fee-section">
<h2>Handling and Additional Charges</h2>
<div class="fee-table-wrap">
<table class="fee-table">
<thead>
<tr>
<th scope="col">Charge</th>
<th scope="col">Price</th>
<th scope="col">Notes</th>
</tr>
</thead>
<tbody>
{additionalCharges.map((row) => (
<tr>
{row.map((cell) => <td>{cell}</td>)}
</tr>
))}
</tbody>
</table>
</div>
</section>
</section>
</BaseLayout>
<style>
.fees-page {
display: grid;
gap: 1.25rem;
}
.fee-section {
padding-block: 0.6rem;
}
.fee-section h2 {
margin: 0 0 0.8rem;
font-family: 'Manrope', system-ui, sans-serif;
font-weight: 800;
}
.fee-table-wrap {
width: 100%;
overflow-x: auto;
margin-block: 0.75rem 1rem;
}
.fee-table {
width: 100%;
min-width: 44rem;
border-collapse: collapse;
border: 1px solid var(--line);
border-radius: var(--radius-sm);
overflow: hidden;
background: rgba(255, 255, 255, 0.86);
box-shadow: 0 12px 24px rgba(16, 34, 51, 0.08);
}
.fee-table-wrap.compact .fee-table {
min-width: 28rem;
}
.fee-table thead {
background: linear-gradient(180deg, rgba(11, 79, 122, 0.14), rgba(29, 118, 184, 0.09));
}
.fee-table th,
.fee-table td {
padding: 0.72rem 0.85rem;
border-bottom: 1px solid var(--line);
text-align: left;
vertical-align: top;
}
.fee-table th {
color: var(--brand);
font-size: 0.82rem;
font-weight: 800;
letter-spacing: 0.04em;
text-transform: uppercase;
white-space: nowrap;
}
.fee-table tbody tr:nth-child(even) {
background: rgba(255, 255, 255, 0.62);
}
.fee-table tbody tr:last-child td {
border-bottom: 0;
}
.fee-section ul {
margin-top: 0.6rem;
}
</style>
+4
View File
@@ -20,6 +20,10 @@ import BaseLayout from '../../layouts/BaseLayout.astro';
<h3><a href="/about/drones/">Drones</a></h3>
<p>Guidance and local operating expectations for drone use near the airport.</p>
</article>
<article class="card">
<h3><a href="/about/fees-and-charges/">Fees and Charges</a></h3>
<p>Landing, parking, handling, passenger loading, drone, and related operational charges.</p>
</article>
<article class="card">
<h3><a href="/about/noise/">Noise</a></h3>
<p>Information about noise awareness, reporting, and community engagement.</p>
+10
View File
@@ -0,0 +1,10 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import DroneFlightRequestForm from '../components/DroneFlightRequestForm.astro';
---
<BaseLayout title="Drone Flight Request" description="Request a drone flight within the Swansea Airport FRZ.">
<div class="container prose">
<DroneFlightRequestForm />
</div>
</BaseLayout>
+1 -1
View File
@@ -66,7 +66,7 @@ const businessPromos = [
</p>
<div class="cta-row">
<a class="button primary" href="/pilot-info/">Pilot Info</a>
<a class="button secondary" href="/procedures-safety-noise-abatement/">Procedures and safety</a>
<a class="button primary" href="/ppr/">Request PPR</a>
</div>
</div>
</div>
+61 -7
View File
@@ -24,13 +24,72 @@ const fuelPrices = await getFuelPrices();
<BaseLayout title="Pilot Info" description="Essential information for pilots planning a visit to Swansea Airport.">
<div class="container prose">
<p class="eyebrow">Pilot info</p>
<h1 class="section-title">Operating hours</h1>
<p><strong>Airport open:</strong> Monday to Sunday, 0900-1800 local time.</p>
<p><strong>Licensed with fire cover:</strong> Friday, Saturday, and Sunday only. RFFS Cat A1.</p>
<h1 class="section-title">Communications</h1>
<p>
Swansea Airport operates a Air / Ground Communication Service, callsign Swansea Radio on 119.705. This service is staffed by volunteers and may not be operational at all times.
Swansea Airport operates a Air / Ground Communication Service, callsign SWANSEA RADIO on 119.705. This service is staffed by volunteers and may not be operational at all times.
</p>
<p>
When the Tower is unavailable, this will be NOTAMed and blind calls to Swansea Traffic shall be made on the Air / Ground frequency
When the Tower is unavailable, this will be NOTAMed and blind calls to Swansea Traffic shall be made on the Air / Ground frequency.
</p>
<p>Please submit your PPR request before flying into Swansea.</p>
<center><a class="button primary" href="/ppr/">Request PPR</a></center>
<h2>Procedures</h2>
<p>
<img src="/images/SDMAP.png" alt="Swansea Airport procedures map" loading="lazy" />
</p>
<h3>Arrivals</h3>
<p>
Make your initial arrival call 10 NM from the ATZ. From the east, this is above Port Talbot.
From the north, this is above Ammanford/Tycroes. From the west, this is just off the Gower
coast approaching Rhossili. From the south, this is over the sea abeam Porthcawl.
</p>
<p>
The Air/Ground service will advise if parachuting is in progress, as well as providing the
usual joining information. If parachuting is in progress, <strong>no overhead joins are permitted</strong>
and there is to be <strong>no dead-side flight within the ATZ</strong>.
</p>
<p>All joins are to be downwind or base leg joins only.</p>
<p>
When already on frequency, parachuting will be notified by the Air/Ground service using the
following message:
</p>
<blockquote>
ALL STATIONS, THIS IS SWANSEA RADIO. PARACHUTING HAS COMMENCED ON THE NORTHERN/SOUTHERN PLA.
NO OVERHEAD JOINS, NO DEAD SIDE FLIGHT.
</blockquote>
<p>
When this is called, <strong>no overhead joins or dead-side flight is permitted in the ATZ</strong>.
</p>
<h3>Departures</h3>
<p>
<strong>All helicopters are to request start.</strong> This is to protect parachuting operations.
If parachuting descent is already taking place, pilots will be advised to start only after the
parachuting descent has completed.
</p>
<p>When parachuting is in progress, all departing aircraft should:</p>
<ul>
<li>Climb straight ahead until clear of the ATZ.</li>
<li>Climb on the crosswind until clear of the ATZ.</li>
</ul>
<p>
<strong>Helicopters are to adhere to the circuit patterns when parachuting is taking place.</strong>
</p>
<p>
<strong>
Be advised that these procedures form part of the rules of the aerodrome. Permission to use
the aerodrome will be revoked if they are not adhered to.
</strong>
</p>
<h2>Runway Information</h2>
<div class="runway-table-wrap">
@@ -64,11 +123,6 @@ When the Tower is unavailable, this will be NOTAMed and blind calls to Swansea T
</ul>
)}
<p>Circuits at 1000ft agl. Overhead joins and/or dead-side flying not permitted when Parachuting is active.
</p>
<FuelPricesWidget fuelPrices={fuelPrices} />
+10
View File
@@ -0,0 +1,10 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import PprRequestForm from '../components/PprRequestForm.astro';
---
<BaseLayout title="Request PPR" description="Submit a prior permission request for flights into Swansea Airport.">
<div class="container prose">
<PprRequestForm />
</div>
</BaseLayout>
@@ -1,29 +0,0 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout title="Procedures, Safety and Noise Abatement" description="Operational procedures, safety notes, and noise-sensitive guidance.">
<div class="container prose">
<p class="eyebrow">Operations</p>
<h1 class="section-title">Procedures, safety, and noise abatement</h1>
<p>
This page is intentionally text-led and easy to scan. It is controlled by Astro so the structure stays stable even as the content evolves.
</p>
<h2>Safety priorities</h2>
<div class="cards-grid">
<article class="card">
<h3>Brief before flight</h3>
<p>Surface the checklist items pilots need most, without burying them under visual clutter.</p>
</article>
<article class="card">
<h3>Check current notices</h3>
<p>Operational notices should be reviewed before taxi, because the homepage is fed by the same notices collection.</p>
</article>
<article class="card">
<h3>Respect local noise guidance</h3>
<p>Noise abatement text can be expanded in Directus while the page structure stays fixed in code.</p>
</article>
</div>
</div>
</BaseLayout>