Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
<SpaRoot>..\jmayer.example.aspreact.client</SpaRoot>
<SpaProxyLaunchCommand>npm run dev</SpaProxyLaunchCommand>
<SpaProxyServerUrl>https://localhost:5173</SpaProxyServerUrl>
<Version>9.0.0</Version>
<Version>9.0.1</Version>
<Authors>jmayer913</Authors>
<Company>jmayer913</Company>
<RepositoryUrl>https://github.com/jmayer913/JMayer-Example-ASPReact</RepositoryUrl>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JMayer.Web.Mvc" Version="9.0.0" />
<PackageReference Include="JMayer.Web.Mvc" Version="9.0.2" />
<PackageReference Include="Microsoft.AspNetCore.SpaProxy">
<Version>9.0.11</Version>
<Version>9.0.12</Version>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.0" />
</ItemGroup>
Expand Down
44 changes: 39 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,30 @@ find a flight in the flight schedule to determine what sort destination the bag

On startup, the example project pregenerates a few airlines, gates and sort destinations and then, a flight schedule is pregenerated; a flight every 10 minutes between 4AM and 10PM. The example has two pages, airlines and flight schedule.

## Airline
## Airlines Page

The airlines page allows the user to add/edit/delete airlines.

<img width="1919" alt="image" src="https://github.com/user-attachments/assets/ef3c14f2-02a2-478b-aab8-9ec72e8824e1" />
<img width="1919" height="590" alt="image" src="https://github.com/user-attachments/assets/10863f13-529e-4c2a-aa07-c05cb587803f" />

### Add / Edit

On the airlines page, the user can create a new airline or edit an existing airline.

* Name - The friendly name for the airline; required and must be unique.
* Description - A description about the airline; optional.
* IATA - The code assigned by the International Air Transport Association to the airline; required and must be two letters or a letter and a number.
* ICAO - The code assigned by the International Civil Aviation Organization to the airline; required, must be 3 letters and must be unique.
* Number Code - The number code assigned by the International Air Transport Association to the airline; required, must be 3 digits and must be unique unless 000 (unassigned).
* Sort Destination - The default sort destination for the airline; required.

<img width="401" height="553" alt="image" src="https://github.com/user-attachments/assets/f25e4ee8-f610-425f-a88f-f7422c7dae31" />

<img width="398" height="549" alt="image" src="https://github.com/user-attachments/assets/ebe27af6-34f3-4b20-ac5c-040d5bbb7bb2" />

<img width="425" alt="image" src="https://github.com/user-attachments/assets/a7e93abf-cb9d-458a-824d-fc496cbcb775" />
### Delete

<img width="407" alt="image" src="https://github.com/user-attachments/assets/108c4aa0-0d33-4c35-ba09-99442a745c58" />
On the airlines page, the user can delete an airline. The user will be required to confirm the deletion or cancel. On confirmation, the airline and its associated flights will be deleted.

<img width="413" alt="image" src="https://github.com/user-attachments/assets/de48d6ec-4046-44fa-850c-298005312601" />

Expand All @@ -21,14 +37,32 @@ The flight schedule page allows the user to add/edit/delete flights in the sched

<img width="1906" alt="image" src="https://github.com/user-attachments/assets/91b40650-d124-451c-8515-8837d9e1e107" />

### Add / Edit

On the flight schedule page, the user can create a new flight or edit an existing flight.

* Gate - The gate the flight will be docked at for departure; required.
* Airline - The airline which owns the plane; required.
* Flight Number - The number assigned to the flight; required and must be 4 digits or 4 digits and a letter.
* Destination - The next destination for the flight; required and must be 3 letters.
* Depart Time - The schedule time the plane will depart from the gate; required.
* Sort Destination - The sort destination bags will be sorted too for the flight; required.

If the flight's airline, flight number and destination match another flight, the add or edit will be rejected by the server.

<img width="404" alt="image" src="https://github.com/user-attachments/assets/cd3dbf00-6797-4f05-b683-7fe5b8e49294" />

<img width="401" alt="image" src="https://github.com/user-attachments/assets/9953df72-ecef-45fb-9821-95964a7e45ba" />

<img width="399" alt="image" src="https://github.com/user-attachments/assets/cd04326b-4f16-4b9a-90e8-1f2a7a86b020" />
### Delete

On the flight schedule page, the user can delete a flight. The user will be required to confirm the deletion or cancel. On confirmation, the flight will be deleted.

<img width="399" alt="image" src="https://github.com/user-attachments/assets/cd04326b-4f16-4b9a-90e8-1f2a7a86b020" />

## Edit Conflict

When two users are editing an airline or flight at the same time, whoever submits first will win; the other user will be told to try again.

<img width="400" height="188" alt="image" src="https://github.com/user-attachments/assets/f5c7e697-7ba7-4177-bd40-4be5d3a03a95" />

4 changes: 2 additions & 2 deletions TestProject/TestProject.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<Version>9.0.0</Version>
<Version>9.0.1</Version>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.12" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
Expand Down
64 changes: 32 additions & 32 deletions jmayer.example.aspreact.client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion jmayer.example.aspreact.client/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "jmayer.example.aspreact.client",
"private": true,
"version": "9.0.0",
"version": "9.0.1",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
16 changes: 11 additions & 5 deletions jmayer.example.aspreact.client/src/datalayers/AirlineDataLayer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ export function useAirlineDataLayer() {
const [updateAirlineSuccess, setUpdateAirlineSuccess] = useState(false);
const [updateAirlineValidationProblemDetails, setUpdateAirlineValidationProblemDetails] = useState(null);

//Constants for the status codes returned by the server.
const BadRequestCode = 400;
const NotFoundCode = 404;
const ConflictCode = 409;
const InternalServerError = 500;

//The function adds an airline to the server.
//@param {object} airline The airline to add.
const addAirline = (airline) => {
Expand All @@ -39,10 +45,10 @@ export function useAirlineDataLayer() {
if (response.ok) {
setAddAirlineSuccess(true);
}
else if (response.status === 400) {
else if (response.status === BadRequestCode) {
response.json().then(validationProblemDetails => setAddAirlineValidationProblemDetails(validationProblemDetails));
}
else if (response.status === 500) {
else if (response.status === InternalServerError) {
response.json().then(problemDetails => showError(problemDetails.detail));
}
else {
Expand Down Expand Up @@ -73,7 +79,7 @@ export function useAirlineDataLayer() {
if (response.ok) {
setDeleteAirlineSuccess(true);
}
else if (response.status === 500) {
else if (response.status === NotFoundCode || response.status === InternalServerError) {
response.json().then(problemDetails => showError(problemDetails.detail));
}
else {
Expand Down Expand Up @@ -107,10 +113,10 @@ export function useAirlineDataLayer() {
if (response.ok) {
setUpdateAirlineSuccess(true);
}
else if (response.status === 400) {
else if (response.status === BadRequestCode) {
response.json().then(validationProblemDetails => setUpdateAirlineValidationProblemDetails(validationProblemDetails));
}
else if (response.status == 409 || response.status === 500) {
else if (response.status === NotFoundCode || response.status == ConflictCode || response.status === InternalServerError) {
response.json().then(problemDetails => showError(problemDetails.detail));
}
else {
Expand Down
16 changes: 11 additions & 5 deletions jmayer.example.aspreact.client/src/datalayers/FlightDataLayer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ export function useFlightDataLayer() {
const [updateFlightSuccess, setUpdateFlightSuccess] = useState(false);
const [updateFlightValidationProblemDetails, setUpdateFlightValidationProblemDetails] = useState(null);

//Constants for the status codes returned by the server.
const BadRequestCode = 400;
const NotFoundCode = 404;
const ConflictCode = 409;
const InternalServerError = 500;

//The function adds a flight to the server.
//@param {object} flight The flight to add.
const addFlight = (flight) => {
Expand All @@ -45,10 +51,10 @@ export function useFlightDataLayer() {
if (response.ok) {
setAddFlightSuccess(true);
}
else if (response.status === 400) {
else if (response.status === BadRequestCode) {
response.json().then(validationProblemDetails => setAddFlightValidationProblemDetails(validationProblemDetails));
}
else if (response.status === 500) {
else if (response.status === InternalServerError) {
response.json().then(problemDetails => showError(problemDetails.detail));
}
else {
Expand Down Expand Up @@ -79,7 +85,7 @@ export function useFlightDataLayer() {
if (response.ok) {
setDeleteFlightSuccess(true);
}
else if (response.status === 500) {
else if (response.status === NotFoundCode || response.status === InternalServerError) {
response.json().then(problemDetails => showError(problemDetails.detail));
}
else {
Expand Down Expand Up @@ -125,10 +131,10 @@ export function useFlightDataLayer() {
if (response.ok) {
setUpdateFlightSuccess(true);
}
else if (response.status === 400) {
else if (response.status === BadRequestCode) {
response.json().then(validationProblemDetails => setUpdateFlightValidationProblemDetails(validationProblemDetails));
}
else if (response.status == 409 || response.status === 500) {
else if (response.status === NotFoundCode || response.status == ConflictCode || response.status === InternalServerError) {
response.json().then(problemDetails => showError(problemDetails.detail));
}
else {
Expand Down