Compare commits
11 Commits
4a0f5dc0bd
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ac31f96df | |||
| 666ed27772 | |||
| 72914f8fe7 | |||
| 50c7d92b45 | |||
| 63db842f1c | |||
| 037f81385c | |||
| 10aec32770 | |||
| 9af555bd25 | |||
| dcae169c28 | |||
| 03c91f7dc9 | |||
| 7603469aae |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -221,7 +221,7 @@ rcf/
|
|||||||
AppPackages/
|
AppPackages/
|
||||||
BundleArtifacts/
|
BundleArtifacts/
|
||||||
Package.StoreAssociation.xml
|
Package.StoreAssociation.xml
|
||||||
_pkginfo.txt
|
*.txt
|
||||||
*.appx
|
*.appx
|
||||||
*.appxbundle
|
*.appxbundle
|
||||||
*.appxupload
|
*.appxupload
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -11,7 +11,6 @@ namespace SkyTeam
|
|||||||
{
|
{
|
||||||
public AdminDashboard()
|
public AdminDashboard()
|
||||||
{
|
{
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
LoadUsers();
|
LoadUsers();
|
||||||
LoadFlights();
|
LoadFlights();
|
||||||
@@ -20,15 +19,12 @@ namespace SkyTeam
|
|||||||
|
|
||||||
private void LoadUsers()
|
private void LoadUsers()
|
||||||
{
|
{
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
BindGrid("SELECT Id, Vorname, Nachname, Email, Rolle FROM users", AllUsersGrid);
|
BindGrid("SELECT Id, Vorname, Nachname, Email, Rolle FROM users", AllUsersGrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AllUsersGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void AllUsersGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (AllUsersGrid.SelectedItem == null) return;
|
if (AllUsersGrid.SelectedItem == null) return;
|
||||||
|
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
DataRowView row = (DataRowView)AllUsersGrid.SelectedItem;
|
DataRowView row = (DataRowView)AllUsersGrid.SelectedItem;
|
||||||
int userId = Convert.ToInt32(row["Id"]);
|
int userId = Convert.ToInt32(row["Id"]);
|
||||||
BindGrid($"SELECT b.Id AS BuchungId, f.Flugnummer, f.Abflugort, f.Zielort, f.Abflugdatum FROM buchungen b JOIN fluege f ON b.FlugId = f.Id WHERE b.UserId = {userId}", UserBookingsGrid);
|
BindGrid($"SELECT b.Id AS BuchungId, f.Flugnummer, f.Abflugort, f.Zielort, f.Abflugdatum FROM buchungen b JOIN fluege f ON b.FlugId = f.Id WHERE b.UserId = {userId}", UserBookingsGrid);
|
||||||
@@ -42,12 +38,6 @@ namespace SkyTeam
|
|||||||
|
|
||||||
if (MessageBox.Show($"User {uid} löschen?", "Confirm", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
|
if (MessageBox.Show($"User {uid} löschen?", "Confirm", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
|
||||||
{
|
{
|
||||||
// Quelle: AI Assistant (Claude ai)
|
|
||||||
// Idee: Sicherheits Risiko Bewertung (Risk Assessment)
|
|
||||||
// Die KI hat angemerkt, dass String Interpolation ($"DELETE... {uid}") bei SQL Queries
|
|
||||||
// normalerweise ein No Go ist (SQL Injection Gefahr). Da wir hier aber sicherstellen, dass 'uid'
|
|
||||||
// zwingend ein Integer (Convert.ToInt32) aus unserer eigenen Datenquelle ist, ist es in diesem
|
|
||||||
// spezifischen Fall für ein Admin Tool vertretbar und spart Code.
|
|
||||||
ExecuteSql($"DELETE FROM users WHERE Id={uid}");
|
ExecuteSql($"DELETE FROM users WHERE Id={uid}");
|
||||||
LoadUsers();
|
LoadUsers();
|
||||||
UserBookingsGrid.ItemsSource = null;
|
UserBookingsGrid.ItemsSource = null;
|
||||||
@@ -56,7 +46,6 @@ namespace SkyTeam
|
|||||||
|
|
||||||
private void LoadFlights()
|
private void LoadFlights()
|
||||||
{
|
{
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
string q = @"SELECT f.Id, f.Flugnummer, f.Abflugort, f.Zielort, f.Abflugdatum, f.Preis,
|
string q = @"SELECT f.Id, f.Flugnummer, f.Abflugort, f.Zielort, f.Abflugdatum, f.Preis,
|
||||||
z.Modell AS Plane, CONCAT(p.Vorname, ' ', p.Nachname) AS Pilot
|
z.Modell AS Plane, CONCAT(p.Vorname, ' ', p.Nachname) AS Pilot
|
||||||
FROM fluege f
|
FROM fluege f
|
||||||
@@ -72,6 +61,12 @@ namespace SkyTeam
|
|||||||
DataRowView row = (DataRowView)AllFlightsGrid.SelectedItem;
|
DataRowView row = (DataRowView)AllFlightsGrid.SelectedItem;
|
||||||
if (MessageBox.Show("Flug löschen?", "Confirm", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
|
if (MessageBox.Show("Flug löschen?", "Confirm", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
|
||||||
{
|
{
|
||||||
|
// Quelle: AI Assistant (Claude ai)
|
||||||
|
// Idee: Sicherheits Risiko Bewertung (Risk Assessment)
|
||||||
|
// Die KI hat angemerkt, dass String Interpolation ($"DELETE... {uid}") bei SQL Queries
|
||||||
|
// normalerweise ein No Go ist (SQL Injection Gefahr). Da wir hier aber sicherstellen, dass 'uid'
|
||||||
|
// zwingend ein Integer (Convert.ToInt32) aus unserer eigenen Datenquelle ist, ist es in diesem
|
||||||
|
// spezifischen Fall für ein Admin Tool vertretbar und spart Code.
|
||||||
ExecuteSql($"DELETE FROM fluege WHERE Id={row["Id"]}");
|
ExecuteSql($"DELETE FROM fluege WHERE Id={row["Id"]}");
|
||||||
LoadFlights();
|
LoadFlights();
|
||||||
}
|
}
|
||||||
@@ -79,7 +74,7 @@ namespace SkyTeam
|
|||||||
|
|
||||||
private void AddFlight_Click(object sender, RoutedEventArgs e)
|
private void AddFlight_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
if (string.IsNullOrWhiteSpace(AddFromCombo.Text) ||
|
if (string.IsNullOrWhiteSpace(AddFromCombo.Text) ||
|
||||||
string.IsNullOrWhiteSpace(AddToCombo.Text) ||
|
string.IsNullOrWhiteSpace(AddToCombo.Text) ||
|
||||||
AddDatePick.SelectedDate == null ||
|
AddDatePick.SelectedDate == null ||
|
||||||
@@ -111,7 +106,6 @@ namespace SkyTeam
|
|||||||
// Wir nutzen die eingebaute AddHours-Methode von DateTime, um automatisch
|
// Wir nutzen die eingebaute AddHours-Methode von DateTime, um automatisch
|
||||||
// ein fiktives Ankunftsdatum zu generieren (Abflug + 4 Stunden)
|
// ein fiktives Ankunftsdatum zu generieren (Abflug + 4 Stunden)
|
||||||
cmd.Parameters.AddWithValue("@arr", AddDatePick.SelectedDate.Value.AddHours(4));
|
cmd.Parameters.AddWithValue("@arr", AddDatePick.SelectedDate.Value.AddHours(4));
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@fnum", flightNum);
|
cmd.Parameters.AddWithValue("@fnum", flightNum);
|
||||||
cmd.Parameters.AddWithValue("@price", AddPriceTxt.Text);
|
cmd.Parameters.AddWithValue("@price", AddPriceTxt.Text);
|
||||||
cmd.Parameters.AddWithValue("@plane", PlaneCombo.SelectedValue);
|
cmd.Parameters.AddWithValue("@plane", PlaneCombo.SelectedValue);
|
||||||
@@ -141,10 +135,9 @@ namespace SkyTeam
|
|||||||
{
|
{
|
||||||
try { using (var c = new MySqlConnection(DatenbankServices.GetConnection())) { c.Open(); var a = new MySqlDataAdapter(q, c); var t = new DataTable(); a.Fill(t); g.ItemsSource = t.DefaultView; } } catch { }
|
try { using (var c = new MySqlConnection(DatenbankServices.GetConnection())) { c.Open(); var a = new MySqlDataAdapter(q, c); var t = new DataTable(); a.Fill(t); g.ItemsSource = t.DefaultView; } } catch { }
|
||||||
}
|
}
|
||||||
|
// Quelle: Microsoft Learn
|
||||||
// Quelle: Microsoft Learn
|
// Hier nutzen wir DisplayMemberPath für den Text, den der User sieht (z.B. das Flugzeugmodell)
|
||||||
// Hier nutzen wir DisplayMemberPath für den Text, den der User sieht (z.B. das Flugzeugmodell)
|
// und SelectedValuePath für den Wert, der im Hintergrund für die Datenbankabfrage genutzt wird (z.B. die Id).
|
||||||
// und SelectedValuePath für den Wert, der im Hintergrund für die Datenbankabfrage genutzt wird (z.B. die Id).
|
|
||||||
private void BindComboBox(string q, ComboBox b, string d, string v)
|
private void BindComboBox(string q, ComboBox b, string d, string v)
|
||||||
{
|
{
|
||||||
try { using (var c = new MySqlConnection(DatenbankServices.GetConnection())) { c.Open(); var a = new MySqlDataAdapter(q, c); var t = new DataTable(); a.Fill(t); b.ItemsSource = t.DefaultView; b.DisplayMemberPath = d; b.SelectedValuePath = v; } } catch { }
|
try { using (var c = new MySqlConnection(DatenbankServices.GetConnection())) { c.Open(); var a = new MySqlDataAdapter(q, c); var t = new DataTable(); a.Fill(t); b.ItemsSource = t.DefaultView; b.DisplayMemberPath = d; b.SelectedValuePath = v; } } catch { }
|
||||||
@@ -155,7 +148,6 @@ namespace SkyTeam
|
|||||||
try { using (var c = new MySqlConnection(DatenbankServices.GetConnection())) { c.Open(); new MySqlCommand(s, c).ExecuteNonQuery(); } } catch (Exception ex) { MessageBox.Show(ex.Message); }
|
try { using (var c = new MySqlConnection(DatenbankServices.GetConnection())) { c.Open(); new MySqlCommand(s, c).ExecuteNonQuery(); } } catch (Exception ex) { MessageBox.Show(ex.Message); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
private void ShowUsers_Click(object sender, RoutedEventArgs e)
|
private void ShowUsers_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
UserManagementGrid.Visibility = Visibility.Visible;
|
UserManagementGrid.Visibility = Visibility.Visible;
|
||||||
|
|||||||
@@ -10,27 +10,22 @@ namespace SkyTeam
|
|||||||
public partial class AdminLoginPage : Page
|
public partial class AdminLoginPage : Page
|
||||||
{
|
{
|
||||||
// Quelle: Microsoft Learn
|
// Quelle: Microsoft Learn
|
||||||
// Nutzung eines "Expression bodied members" (=>) für den Konstruktor
|
// Nutzung eines "Expression bodied members" (=>) für den Konstruktor
|
||||||
// Das macht Methoden oder Konstruktoren, die nur aus einer einzigen Zeile bestehen,
|
// Das macht Methoden oder Konstruktoren, die nur aus einer einzigen Zeile bestehen,
|
||||||
// deutlich kompakter und besser lesbar
|
// deutlich kompakter und besser lesbar
|
||||||
public AdminLoginPage() => InitializeComponent();
|
public AdminLoginPage() => InitializeComponent();
|
||||||
|
|
||||||
private void AdminLogin_Click(object sender, RoutedEventArgs e)
|
private void AdminLogin_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
|
|
||||||
string query = "SELECT Id, PasswortHash FROM users WHERE Email = @email AND Vorname = @user AND Rolle = @role";
|
string query = "SELECT Id, PasswortHash FROM users WHERE Email = @email AND Vorname = @user AND Rolle = @role";
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
|
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
|
||||||
{
|
{
|
||||||
conn.Open();
|
conn.Open();
|
||||||
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
using (MySqlCommand cmd = new MySqlCommand(query, conn))
|
||||||
{
|
{
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@email", AdminEmailBox.Text);
|
cmd.Parameters.AddWithValue("@email", AdminEmailBox.Text);
|
||||||
cmd.Parameters.AddWithValue("@user", AdminUserBox.Text);
|
cmd.Parameters.AddWithValue("@user", AdminUserBox.Text);
|
||||||
cmd.Parameters.AddWithValue("@role", AdminRoleBox.Text);
|
cmd.Parameters.AddWithValue("@role", AdminRoleBox.Text);
|
||||||
@@ -49,9 +44,9 @@ namespace SkyTeam
|
|||||||
if (BCrypt.Net.BCrypt.Verify(AdminPassBox.Password, storedHash))
|
if (BCrypt.Net.BCrypt.Verify(AdminPassBox.Password, storedHash))
|
||||||
{
|
{
|
||||||
// Quelle: AI Assistant (Gemini)
|
// Quelle: AI Assistant (Gemini)
|
||||||
// Konsistentes State Management
|
// Konsistentes State Management
|
||||||
// Kommentar: Wir nutzen wieder den statischen SessionManager, den die KI für das
|
// Kommentar: Wir nutzen wieder den statischen SessionManager, den die KI für das
|
||||||
// Haupt Login vorgeschlagen hatte. So weiß das AdminDashboard sofort, wer eingeloggt ist
|
// Haupt Login vorgeschlagen hatte. So weiß das AdminDashboard sofort, wer eingeloggt ist
|
||||||
SessionManager.CurrentUserId = dbId;
|
SessionManager.CurrentUserId = dbId;
|
||||||
SessionManager.CurrentUserName = AdminUserBox.Text;
|
SessionManager.CurrentUserName = AdminUserBox.Text;
|
||||||
|
|
||||||
@@ -77,7 +72,6 @@ namespace SkyTeam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
private void Back_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new LogInPage());
|
private void Back_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new LogInPage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,25 @@
|
|||||||
using BCrypt.Net;
|
using BCrypt.Net;
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
using System;
|
using PdfSharp.Fonts;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Threading;
|
using System.Reflection;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using static SkyTeam.BuchungenPage;
|
||||||
|
|
||||||
namespace SkyTeam
|
namespace SkyTeam
|
||||||
{
|
{
|
||||||
public partial class App : Application
|
public partial class App : Application
|
||||||
{
|
{
|
||||||
// Beim Start der Anwendung einen Standard Admin Benutzer erstellen, falls keiner existiert
|
// Beim Start der Anwendung einen Standard Admin-Benutzer erstellen, falls keiner existiert , selbGedacht.
|
||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
// Quelle: Stack Overflow
|
// Quelle: Stack Overflow
|
||||||
// Durch das Setzen der CurrentUICulture direkt im App-Konstruktor stellen wir sicher,
|
// Durch das Setzen der CurrentUICulture direkt im App-Konstruktor stellen wir sicher,
|
||||||
// dass die gesamte Anwendung (alle Pages und Windows) von Anfang an die gleiche Spracheinstellung
|
// dass die gesamte Anwendung (alle Pages und Windows) von Anfang an die gleiche Spracheinstellung
|
||||||
// nutzt. Das verhindert Inkonsistenzen beim Laden der ersten Seite.
|
// nutzt. Das verhindert Inkonsistenzen beim Laden der ersten Seite.
|
||||||
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de");
|
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de");
|
||||||
|
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de");
|
||||||
// Quelle: AI Assistant (Gemini)
|
GlobalFontSettings.FontResolver = new CustomFontResolver();
|
||||||
// Idee: Code-Bereinigung / Refactoring
|
|
||||||
// Die Zuweisung der Culture stand hier ursprünglich doppelt. Die KI hat beim
|
|
||||||
// Code Review darauf hingewiesen, dass eine einmalige Zuweisung ausreicht, um Redundanzen
|
|
||||||
// zu vermeiden. Die zweite Zeile wurde entfernt.
|
|
||||||
|
|
||||||
CreateDefaultAdmin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateDefaultAdmin()
|
private void CreateDefaultAdmin()
|
||||||
@@ -36,27 +31,23 @@ namespace SkyTeam
|
|||||||
using (MySqlConnection conn = new MySqlConnection(connectionString))
|
using (MySqlConnection conn = new MySqlConnection(connectionString))
|
||||||
{
|
{
|
||||||
conn.Open();
|
conn.Open();
|
||||||
|
|
||||||
// Quelle: Stack Overflow
|
// Quelle: Stack Overflow
|
||||||
// Dieses Architektur-Muster nennt sich "Database Seeding". Es stellt sicher,
|
// Dieses Architektur-Muster nennt sich "Database Seeding". Es stellt sicher,
|
||||||
// dass das System nach einer Neuinstallation sofort nutzbar ist, da automatisch ein
|
// dass das System nach einer Neuinstallation sofort nutzbar ist, da automatisch ein
|
||||||
// Root-Account existiert, ohne dass manuelle SQL Eingriffe nötig sind.
|
// Root-Account existiert, ohne dass manuelle SQL Eingriffe nötig sind.
|
||||||
|
|
||||||
string checkQuery = "SELECT COUNT(*) FROM users WHERE Rolle = 'Admin'";
|
string checkQuery = "SELECT COUNT(*) FROM users WHERE Rolle = 'Admin'";
|
||||||
MySqlCommand checkCmd = new MySqlCommand(checkQuery, conn);
|
MySqlCommand checkCmd = new MySqlCommand(checkQuery, conn);
|
||||||
long count = (long)checkCmd.ExecuteScalar();
|
long count = (long)checkCmd.ExecuteScalar();
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
// Quelle: Reddit
|
|
||||||
|
|
||||||
string hashedPassword = BCrypt.Net.BCrypt.HashPassword("admin");
|
string hashedPassword = BCrypt.Net.BCrypt.HashPassword("admin");
|
||||||
|
|
||||||
string insertQuery = @"
|
string insertQuery = @"
|
||||||
INSERT INTO users (Vorname, Nachname, Email, PasswortHash, Rolle, Stadt, CreatedAt)
|
INSERT INTO users (Vorname, Nachname, Email, PasswortHash, Rolle, Stadt, CreatedAt)
|
||||||
VALUES ('System', 'Root', 'admin@skyteam.com', @hash, 'Admin', 'HQ', NOW())";
|
VALUES ('System', 'Root', 'admin@skyteam.com', @hash, 'Admin', 'HQ', NOW())";
|
||||||
|
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
|
|
||||||
MySqlCommand insertCmd = new MySqlCommand(insertQuery, conn);
|
MySqlCommand insertCmd = new MySqlCommand(insertQuery, conn);
|
||||||
insertCmd.Parameters.AddWithValue("@hash", hashedPassword);
|
insertCmd.Parameters.AddWithValue("@hash", hashedPassword);
|
||||||
insertCmd.ExecuteNonQuery();
|
insertCmd.ExecuteNonQuery();
|
||||||
@@ -65,8 +56,8 @@ namespace SkyTeam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch(Exception ex) {
|
||||||
{
|
|
||||||
MessageBox.Show("Fehler beim Erstellen des Standard Admins: " + ex.Message);
|
MessageBox.Show("Fehler beim Erstellen des Standard Admins: " + ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,7 @@
|
|||||||
</DataGrid>
|
</DataGrid>
|
||||||
|
|
||||||
<Button x:Name="CancelBtn" Visibility="Collapsed" Content="{x:Static properties:Resources.CancelFlightButton}" Background="#D32F2F" Foreground="White" FontWeight="Bold" Width="150" Height="40" HorizontalAlignment="Right" Margin="0,15,0,0" Click="CancelBooking_Click"/>
|
<Button x:Name="CancelBtn" Visibility="Collapsed" Content="{x:Static properties:Resources.CancelFlightButton}" Background="#D32F2F" Foreground="White" FontWeight="Bold" Width="150" Height="40" HorizontalAlignment="Right" Margin="0,15,0,0" Click="CancelBooking_Click"/>
|
||||||
|
<Button x:Name="CreatePdfBtn" Visibility="Collapsed" Content="{x:Static properties:Resources.CreatePdfButton}" Background="#FF1E88E5" Foreground="White" FontWeight="Bold" Width="150" Height="40" HorizontalAlignment="Right" Margin="0,15,0,0" Click="CreatePdf_Click"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
using System;
|
using MySql.Data.MySqlClient;
|
||||||
|
using PdfSharp.Drawing;
|
||||||
|
using PdfSharp.Fonts;
|
||||||
|
using PdfSharp.Pdf;
|
||||||
|
using System;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using MySql.Data.MySqlClient;
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace SkyTeam
|
namespace SkyTeam
|
||||||
{
|
{
|
||||||
@@ -41,12 +46,14 @@ namespace SkyTeam
|
|||||||
NoBookingsView.Visibility = Visibility.Collapsed;
|
NoBookingsView.Visibility = Visibility.Collapsed;
|
||||||
BookingsGrid.Visibility = Visibility.Visible;
|
BookingsGrid.Visibility = Visibility.Visible;
|
||||||
CancelBtn.Visibility = Visibility.Visible;
|
CancelBtn.Visibility = Visibility.Visible;
|
||||||
|
CreatePdfBtn.Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NoBookingsView.Visibility = Visibility.Visible;
|
NoBookingsView.Visibility = Visibility.Visible;
|
||||||
BookingsGrid.Visibility = Visibility.Collapsed;
|
BookingsGrid.Visibility = Visibility.Collapsed;
|
||||||
CancelBtn.Visibility = Visibility.Collapsed;
|
CancelBtn.Visibility = Visibility.Collapsed;
|
||||||
|
CreatePdfBtn.Visibility = Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,11 +81,81 @@ namespace SkyTeam
|
|||||||
LoadBookings();
|
LoadBookings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Idee und Grundlage aus folgendem Video:
|
||||||
|
// https://www.youtube.com/watch?v=sfeJprlUT7E
|
||||||
|
// Datum: 05.03.2026
|
||||||
|
// Anpassung und Implementierung mit Unterstützung von ChatGPT (OpenAI)
|
||||||
|
public class CustomFontResolver : IFontResolver
|
||||||
|
{
|
||||||
|
private readonly string fontPath = "OpenSans-Regular.ttf";
|
||||||
|
|
||||||
|
public string DefaultFontName => "OpenSans";
|
||||||
|
|
||||||
|
public byte[] GetFont(string faceName)
|
||||||
|
{
|
||||||
|
return File.ReadAllBytes(fontPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic)
|
||||||
|
{
|
||||||
|
return new FontResolverInfo("OpenSans");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Feature: PDF-Export für Flugbuchungen hinzugefügt
|
||||||
|
//Quelle:
|
||||||
|
//YouTube Tutorial: https://www.youtube.com/watch?v=C-yMypr_TdY
|
||||||
|
//Datum: 05.03.2026
|
||||||
|
private void CreatePdf_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (BookingsGrid.SelectedItem == null)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Bitte wählen Sie einen Flug aus.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataRowView row = (DataRowView)BookingsGrid.SelectedItem;
|
||||||
|
|
||||||
|
int buchungId = Convert.ToInt32(row["BuchungId"]);
|
||||||
|
string flugNr = row["Flugnummer"].ToString();
|
||||||
|
string von = row["Abflugort"].ToString();
|
||||||
|
string nach = row["Zielort"].ToString();
|
||||||
|
DateTime datum = Convert.ToDateTime(row["Abflugdatum"]);
|
||||||
|
string status = row["Status"].ToString();
|
||||||
|
|
||||||
|
string logoPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "icon.png");
|
||||||
|
XImage logo = XImage.FromFile(logoPath);
|
||||||
|
|
||||||
|
PdfDocument document = new PdfDocument();
|
||||||
|
document.Info.Title = "Flugbuchung";
|
||||||
|
|
||||||
|
PdfPage page = document.AddPage();
|
||||||
|
XGraphics gfx = XGraphics.FromPdfPage(page);
|
||||||
|
|
||||||
|
XFont titleFont = new XFont("OpenSans", 30);
|
||||||
|
XFont textFont = new XFont("OpenSans", 20);
|
||||||
|
|
||||||
|
gfx.DrawImage(logo, 40, 20, 100, 100);
|
||||||
|
gfx.DrawString("Flugbuchung", titleFont, XBrushes.Black, new XPoint(200, 80));
|
||||||
|
gfx.DrawString($"Buchung-ID: {buchungId}", textFont, XBrushes.Black, new XPoint(40, 160));
|
||||||
|
gfx.DrawString($"Flug-Nr.: {flugNr}", textFont, XBrushes.Black, new XPoint(40, 200));
|
||||||
|
gfx.DrawString($"Von: {von}", textFont, XBrushes.Black, new XPoint(40, 240));
|
||||||
|
gfx.DrawString($"Nach: {nach}", textFont, XBrushes.Black, new XPoint(40, 280));
|
||||||
|
gfx.DrawString($"Datum: {datum:dd.MM.yyyy}", textFont, XBrushes.Black, new XPoint(40, 320));
|
||||||
|
gfx.DrawString($"Status: {status}", textFont, XBrushes.Black, new XPoint(40, 360));
|
||||||
|
|
||||||
|
string filename = $"Flugbuchung_{buchungId}.pdf";
|
||||||
|
document.Save(filename);
|
||||||
|
|
||||||
|
MessageBox.Show($"PDF erfolgreich erstellt: {filename}");
|
||||||
|
}
|
||||||
|
|
||||||
private void HomeButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new NavigationPage());
|
private void HomeButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new NavigationPage());
|
||||||
private void BookingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new BuchungenPage());
|
private void BookingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new BuchungenPage());
|
||||||
private void SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
|
private void SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
|
||||||
private void LogoutButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new LogInPage());
|
private void LogoutButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new LogInPage());
|
||||||
private void OpenReservierungSuche_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new ReservierungssuchePage());
|
private void OpenReservierungSuche_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new ReservierungssuchePage());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ namespace SkyTeam
|
|||||||
{
|
{
|
||||||
static class DatenbankServices
|
static class DatenbankServices
|
||||||
{
|
{
|
||||||
private static readonly string connectionString = "Server=mysql.pb.bib.de;uid=pbt3h24akh;pwd=Dd3dwQgPeNxW;database=pbt3h24akh_SkyTeam;";
|
private static readonly string connectionString = File.ReadAllText("connectionstring.txt");
|
||||||
|
|
||||||
public static string GetConnection()
|
public static string GetConnection()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using System.Windows.Controls;
|
|||||||
|
|
||||||
namespace SkyTeam
|
namespace SkyTeam
|
||||||
{
|
{
|
||||||
// in unterricht schonmal gemacht , hier nochmal
|
|
||||||
public partial class NavigationPage : Page
|
public partial class NavigationPage : Page
|
||||||
{
|
{
|
||||||
public NavigationPage()
|
public NavigationPage()
|
||||||
|
|||||||
@@ -11,25 +11,22 @@ namespace SkyTeam
|
|||||||
{
|
{
|
||||||
public LogInPage()
|
public LogInPage()
|
||||||
{
|
{
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
// Quelle: Im Unterricht gemacht
|
||||||
private void AdminLink_Click(object sender, RoutedEventArgs e)
|
private void AdminLink_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
|
|
||||||
if (Application.Current.MainWindow is MainWindow mainWindow)
|
if (Application.Current.MainWindow is MainWindow mainWindow)
|
||||||
{
|
{
|
||||||
mainWindow.MainFrame.Navigate(new AdminLoginPage());
|
mainWindow.MainFrame.Navigate(new AdminLoginPage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void LogInButton_Click(object sender, RoutedEventArgs e)
|
private void LogInButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
string email = BenutzernameTextBox.Text;
|
string email = BenutzernameTextBox.Text;
|
||||||
string password = PasswortTextBox.Password;
|
string password = PasswortTextBox.Password;
|
||||||
|
|
||||||
// Quelle: Im Unterricht gemacht
|
// Quelle: Im Unterricht gemacht
|
||||||
// Basis Validierung auf leere Felder
|
// Basis Validierung auf leere Felder
|
||||||
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password))
|
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password))
|
||||||
@@ -60,7 +57,6 @@ namespace SkyTeam
|
|||||||
MessageBox.Show("Benutzer wurde nicht gefunden.");
|
MessageBox.Show("Benutzer wurde nicht gefunden.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quelle: Stack Overflow "How to verify a BCrypt hash"
|
// Quelle: Stack Overflow "How to verify a BCrypt hash"
|
||||||
// Man kann gehashte Passwörter NICHT direkt im SQL Query vergleichen
|
// Man kann gehashte Passwörter NICHT direkt im SQL Query vergleichen
|
||||||
// (z.B. WHERE Hash = @hash), da BCrypt jedes Mal einen neuen, zufälligen Salt generiert.
|
// (z.B. WHERE Hash = @hash), da BCrypt jedes Mal einen neuen, zufälligen Salt generiert.
|
||||||
@@ -73,12 +69,11 @@ namespace SkyTeam
|
|||||||
MessageBox.Show("Falsches Passwort.");
|
MessageBox.Show("Falsches Passwort.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Quelle: AI Assistant (chat gpt)
|
||||||
// Quelle: AI Assistant (chat gpt)
|
// Idee: Globales State-Management über eine statische Klasse (SessionManager)
|
||||||
// Idee: Globales State-Management über eine statische Klasse (SessionManager)
|
// Kommentar: Anstatt die User ID mühsam über jeden Seitenaufruf hinweg in den Konstruktoren
|
||||||
// Kommentar: Anstatt die User ID mühsam über jeden Seitenaufruf hinweg in den Konstruktoren
|
// weiterzureichen, hat die KI vorgeschlagen, eine statische SessionManager Klasse zu nutzen.
|
||||||
// weiterzureichen, hat die KI vorgeschlagen, eine statische SessionManager Klasse zu nutzen.
|
// So sind User-ID, Name und Rolle global für die gesamte Laufzeit abrufbar.
|
||||||
// So sind User-ID, Name und Rolle global für die gesamte Laufzeit abrufbar.
|
|
||||||
SessionManager.CurrentUserId = reader.GetInt32("Id");
|
SessionManager.CurrentUserId = reader.GetInt32("Id");
|
||||||
SessionManager.CurrentUserName = reader.GetString("Vorname");
|
SessionManager.CurrentUserName = reader.GetString("Vorname");
|
||||||
SessionManager.Role = reader.GetString("Rolle");
|
SessionManager.Role = reader.GetString("Rolle");
|
||||||
@@ -97,13 +92,13 @@ namespace SkyTeam
|
|||||||
|
|
||||||
private void anmeldungsButton_Click(object sender, RoutedEventArgs e)
|
private void anmeldungsButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
((MainWindow)Application.Current.MainWindow)
|
((MainWindow)Application.Current.MainWindow)
|
||||||
.MainFrame.Navigate(new RegistrationPage());
|
.MainFrame.Navigate(new RegistrationPage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Page_Loaded(object sender, RoutedEventArgs e)
|
private void Page_Loaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Quelle: Im Unterricht gemacht
|
// Quelle: Im Unterricht gemacht
|
||||||
// Setzt den Cursor direkt beim Laden der Seite ins Benutzernamen-Feld.
|
// Setzt den Cursor direkt beim Laden der Seite ins Benutzernamen-Feld.
|
||||||
BenutzernameTextBox.Focus();
|
BenutzernameTextBox.Focus();
|
||||||
@@ -112,9 +107,9 @@ namespace SkyTeam
|
|||||||
private void BenutzernameTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
|
private void BenutzernameTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
// Quelle: Stack Overflow "WPF Move focus on enter key"
|
// Quelle: Stack Overflow "WPF Move focus on enter key"
|
||||||
// Kommentar: Ein UX-Feature (User Experience). Wenn der User im Textfeld 'Enter' oder die 'Pfeil Runter' Taste
|
// Ein UX Feature (User Experience). Wenn der User im Textfeld 'Enter' oder die 'Pfeil Runter' Taste
|
||||||
// drückt, generieren wir einen TraversalRequest. Dadurch springt der Fokus automatisch ins nächste UI-Element
|
// drückt, generieren wir einen TraversalRequest. Dadurch springt der Fokus automatisch ins nächste UI-Element
|
||||||
// (das Passwort Feld), ohne dass der User die Maus benutzen muss.
|
// (das Passwort Feld), ohne dass der User die Maus benutzen muss
|
||||||
if (e.Key == Key.Down || e.Key == Key.Enter)
|
if (e.Key == Key.Down || e.Key == Key.Enter)
|
||||||
{
|
{
|
||||||
TraversalRequest request =
|
TraversalRequest request =
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
WindowStartupLocation="CenterScreen"
|
WindowStartupLocation="CenterScreen"
|
||||||
WindowState="Maximized">
|
WindowState="Maximized">
|
||||||
|
|
||||||
|
|
||||||
<Window.Effect>
|
<Window.Effect>
|
||||||
<DropShadowEffect/>
|
<DropShadowEffect/>
|
||||||
</Window.Effect>
|
</Window.Effect>
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ namespace SkyTeam
|
|||||||
{
|
{
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
// nichts besonderes, hier wird nur die LoginPage als erstes angezeigt
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|||||||
BIN
SkyTeam/OpenSans-Regular.ttf
Normal file
BIN
SkyTeam/OpenSans-Regular.ttf
Normal file
Binary file not shown.
@@ -11,15 +11,11 @@ namespace SkyTeam
|
|||||||
{
|
{
|
||||||
public RegistrationPage()
|
public RegistrationPage()
|
||||||
{
|
{
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
// Standard-Initialisierung der WPF Komponenten
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterButton_Click(object sender, RoutedEventArgs e)
|
private void RegisterButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
// Grundlegende Validierung, ob die Pflichtfelder ausgefüllt wurden
|
|
||||||
if (string.IsNullOrWhiteSpace(EmailTextBox.Text) || string.IsNullOrWhiteSpace(PasswordBox.Password))
|
if (string.IsNullOrWhiteSpace(EmailTextBox.Text) || string.IsNullOrWhiteSpace(PasswordBox.Password))
|
||||||
{
|
{
|
||||||
MessageBox.Show("Bitte geben Sie Email und Passwort ein.");
|
MessageBox.Show("Bitte geben Sie Email und Passwort ein.");
|
||||||
@@ -40,10 +36,6 @@ namespace SkyTeam
|
|||||||
{
|
{
|
||||||
conn.Open();
|
conn.Open();
|
||||||
|
|
||||||
// Quelle: Stack Overflow - "Check if a row exists with a specific value"
|
|
||||||
// Link: https://stackoverflow.com/questions/2788543/check-if-a-row-exists-with-a-specific-value-in-a-database
|
|
||||||
// Wir nutzen ExecuteScalar() anstelle eines Readers, da wir nur wissen wollen,
|
|
||||||
// ob die Email bereits existiert (COUNT > 0). Das ist wesentlich performanter
|
|
||||||
string checkQuery = "SELECT COUNT(*) FROM users WHERE Email = @email";
|
string checkQuery = "SELECT COUNT(*) FROM users WHERE Email = @email";
|
||||||
using (MySqlCommand checkCmd = new MySqlCommand(checkQuery, conn))
|
using (MySqlCommand checkCmd = new MySqlCommand(checkQuery, conn))
|
||||||
{
|
{
|
||||||
@@ -58,10 +50,6 @@ namespace SkyTeam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quelle: Reddit - r/csharp "How should I store passwords in my database?"
|
|
||||||
// Link: https://www.reddit.com/r/csharp/comments/7qcx8f/how_should_i_store_passwords_in_my_database/
|
|
||||||
// Laut Community Konsens sollten Passwörter niemals im Klartext gespeichert werden
|
|
||||||
// Wir nutzen die BCrypt Bibliothek, die automatisch Salting und Hashing übernimmt , das ist schon mal in Unterricht behandelt worden
|
|
||||||
string hashedPassword = BCrypt.Net.BCrypt.HashPassword(PasswordBox.Password);
|
string hashedPassword = BCrypt.Net.BCrypt.HashPassword(PasswordBox.Password);
|
||||||
string insertQuery = "INSERT INTO users (Vorname, Nachname, Email, PasswortHash, Rolle, Stadt, Anrede, Geburtsdatum) " +
|
string insertQuery = "INSERT INTO users (Vorname, Nachname, Email, PasswortHash, Rolle, Stadt, Anrede, Geburtsdatum) " +
|
||||||
"VALUES (@vorname, @nachname, @email, @password, 'User', @stadt, @anrede, @geburtsdatum)";
|
"VALUES (@vorname, @nachname, @email, @password, 'User', @stadt, @anrede, @geburtsdatum)";
|
||||||
@@ -71,19 +59,16 @@ namespace SkyTeam
|
|||||||
string selectedAnrede = (SalutationComboBox.SelectedItem as ComboBoxItem)?.Content.ToString();
|
string selectedAnrede = (SalutationComboBox.SelectedItem as ComboBoxItem)?.Content.ToString();
|
||||||
DateTime? selectedDate = BirthDatePicker.SelectedDate;
|
DateTime? selectedDate = BirthDatePicker.SelectedDate;
|
||||||
|
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
// Kommentar: Standard Parameter-Binding zum Schutz vor SQL-Injection
|
|
||||||
cmd.Parameters.AddWithValue("@vorname", FirstNameTextBox.Text);
|
cmd.Parameters.AddWithValue("@vorname", FirstNameTextBox.Text);
|
||||||
cmd.Parameters.AddWithValue("@nachname", LastNameTextBox.Text);
|
cmd.Parameters.AddWithValue("@nachname", LastNameTextBox.Text);
|
||||||
cmd.Parameters.AddWithValue("@email", emailToCheck);
|
cmd.Parameters.AddWithValue("@email", emailToCheck);
|
||||||
cmd.Parameters.AddWithValue("@password", hashedPassword);
|
cmd.Parameters.AddWithValue("@password", hashedPassword);
|
||||||
cmd.Parameters.AddWithValue("@stadt", CityTextBox.Text);
|
cmd.Parameters.AddWithValue("@stadt", CityTextBox.Text);
|
||||||
|
|
||||||
// Quelle: Microsoft Learn - "DBNull.Value Field"
|
// Quelle: Microsoft Learn - "DBNull.Value Field"
|
||||||
// Link: https://learn.microsoft.com/en-us/dotnet/api/system.dbnull.value
|
// Link: https://learn.microsoft.com/en-us/dotnet/api/system.dbnull.value
|
||||||
// Wenn optionale Felder (wie Anrede oder Geburtsdatum) leer bleiben,
|
// Wenn optionale Felder (wie Anrede oder Geburtsdatum) leer bleiben,
|
||||||
// können wir nicht einfach 'null' in C# übergeben. Die Datenbank erwartet explizit
|
// können wir nicht einfach 'null' in C# übergeben. Die Datenbank erwartet explizit
|
||||||
// das Objekt 'DBNull.Value', damit die Spalte korrekt als NULL markiert wird
|
// das Objekt 'DBNull.Value', damit die Spalte korrekt als NULL markiert wird
|
||||||
cmd.Parameters.AddWithValue("@anrede", selectedAnrede ?? (object)DBNull.Value);
|
cmd.Parameters.AddWithValue("@anrede", selectedAnrede ?? (object)DBNull.Value);
|
||||||
cmd.Parameters.AddWithValue("@geburtsdatum", selectedDate.HasValue ? selectedDate.Value : (object)DBNull.Value);
|
cmd.Parameters.AddWithValue("@geburtsdatum", selectedDate.HasValue ? selectedDate.Value : (object)DBNull.Value);
|
||||||
|
|
||||||
@@ -92,12 +77,11 @@ namespace SkyTeam
|
|||||||
}
|
}
|
||||||
|
|
||||||
MessageBox.Show("Dein Konto wurde erfolgreich angelegt!");
|
MessageBox.Show("Dein Konto wurde erfolgreich angelegt!");
|
||||||
|
// Quelle: AI Assistant (Gemini)
|
||||||
// Quelle: AI Assistant (Gemini)
|
// Idee: Navigation aus einer Page heraus, die in einem Frame gehostet wird.
|
||||||
// Idee: Navigation aus einer Page heraus, die in einem Frame gehostet wird.
|
// Kommentar: Die KI hat darauf hingewiesen, dass eine Page (wie die RegistrationPage)
|
||||||
// Kommentar: Die KI hat darauf hingewiesen, dass eine Page (wie die RegistrationPage)
|
// nicht direkt navigieren sollte, wenn sie im MainFrame des MainWindows liegt.
|
||||||
// nicht direkt navigieren sollte, wenn sie im MainFrame des MainWindows liegt.
|
// Wir müssen erst auf das MainWindow zugreifen, um dessen Frame für die Navigation zu nutzen.
|
||||||
// Wir müssen erst auf das MainWindow zugreifen, um dessen Frame für die Navigation zu nutzen.
|
|
||||||
if (Application.Current.MainWindow is MainWindow mainWindow)
|
if (Application.Current.MainWindow is MainWindow mainWindow)
|
||||||
{
|
{
|
||||||
mainWindow.MainFrame.Navigate(new LogInPage());
|
mainWindow.MainFrame.Navigate(new LogInPage());
|
||||||
@@ -125,10 +109,10 @@ namespace SkyTeam
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Quelle: Microsoft Learn - "How to verify that strings are in valid email format"
|
// Quelle: Microsoft Learn - "How to verify that strings are in valid email format"
|
||||||
// Link: https://learn.microsoft.com/en-us/dotnet/standard/base-types/how-to-verify-that-strings-are-in-valid-email-format
|
// Link: https://learn.microsoft.com/en-us/dotnet/standard/base-types/how-to-verify-that-strings-are-in-valid-email-format
|
||||||
// Kommentar: Wir nutzen den offiziell empfohlenen Regex-Ausdruck von Microsoft,
|
// Kommentar: Wir nutzen den offiziell empfohlenen Regex-Ausdruck von Microsoft,
|
||||||
// kombiniert mit einem Timeout (250ms), um Denial-of-Service-Angriffe durch
|
// kombiniert mit einem Timeout (250ms), um Denial-of-Service-Angriffe durch
|
||||||
// extrem lange oder fehlerhafte Strings (ReDoS) zu verhindern.
|
// extrem lange oder fehlerhafte Strings (ReDoS) zu verhindern.
|
||||||
return Regex.IsMatch(email,
|
return Regex.IsMatch(email,
|
||||||
@"^[^@\s]+@[^@\s]+\.[^@\s]+$",
|
@"^[^@\s]+@[^@\s]+\.[^@\s]+$",
|
||||||
RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
|
RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
|
||||||
|
|||||||
9
SkyTeam/Resources.Designer.cs
generated
9
SkyTeam/Resources.Designer.cs
generated
@@ -222,6 +222,15 @@ namespace SkyTeam {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sucht eine lokalisierte Zeichenfolge, die Als PDF exportieren ähnelt.
|
||||||
|
/// </summary>
|
||||||
|
public static string CreatePdfButton {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("CreatePdfButton", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sucht eine lokalisierte Zeichenfolge, die Passen Sie Ihr Erlebnis an ähnelt.
|
/// Sucht eine lokalisierte Zeichenfolge, die Passen Sie Ihr Erlebnis an ähnelt.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -285,4 +285,7 @@
|
|||||||
<data name="CancelFlightButton" xml:space="preserve">
|
<data name="CancelFlightButton" xml:space="preserve">
|
||||||
<value>إلغاء الرحلة</value>
|
<value>إلغاء الرحلة</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="CreatePdfButton" xml:space="preserve">
|
||||||
|
<value>تصدير إلى PDF</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -285,4 +285,7 @@
|
|||||||
<data name="CancelFlightButton" xml:space="preserve">
|
<data name="CancelFlightButton" xml:space="preserve">
|
||||||
<value>Cancel Flight</value>
|
<value>Cancel Flight</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="CreatePdfButton" xml:space="preserve">
|
||||||
|
<value>Export as PDF</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -285,4 +285,7 @@
|
|||||||
<data name="CancelFlightButton" xml:space="preserve">
|
<data name="CancelFlightButton" xml:space="preserve">
|
||||||
<value>Flug stornieren</value>
|
<value>Flug stornieren</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="CreatePdfButton" xml:space="preserve">
|
||||||
|
<value>Als PDF exportieren</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -285,4 +285,7 @@
|
|||||||
<data name="CancelFlightButton" xml:space="preserve">
|
<data name="CancelFlightButton" xml:space="preserve">
|
||||||
<value>Скасувати рейс</value>
|
<value>Скасувати рейс</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="CreatePdfButton" xml:space="preserve">
|
||||||
|
<value>Експортувати у PDF</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -27,6 +27,7 @@
|
|||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<StackPanel Grid.Row="1" Grid.Column="0" Background="{DynamicResource SidebarBackground}">
|
<StackPanel Grid.Row="1" Grid.Column="0" Background="{DynamicResource SidebarBackground}">
|
||||||
|
|
||||||
<Button Height="50" Margin="5" Click="HomeButton_Click" Background="Transparent" BorderThickness="0">
|
<Button Height="50" Margin="5" Click="HomeButton_Click" Background="Transparent" BorderThickness="0">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<iconPacks:PackIconMaterial Kind="Home" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
|
<iconPacks:PackIconMaterial Kind="Home" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
|
||||||
@@ -105,103 +106,25 @@
|
|||||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||||
|
|
||||||
<iconPacks:PackIconMaterial Kind="Translate"
|
<iconPacks:PackIconMaterial Kind="Translate"
|
||||||
Width="32" Height="32"
|
Width="32"
|
||||||
|
Height="32"
|
||||||
Foreground="{DynamicResource PrimaryText}"
|
Foreground="{DynamicResource PrimaryText}"
|
||||||
Margin="0,0,15,0"/>
|
Margin="0,0,15,0"/>
|
||||||
|
|
||||||
<StackPanel Width="300">
|
<StackPanel Width="300">
|
||||||
<TextBlock Text="{x:Static properties:Resources.Language}"
|
<TextBlock Text="{x:Static properties:Resources.Language}"
|
||||||
FontSize="18" FontWeight="Bold"
|
FontSize="18"
|
||||||
|
FontWeight="Bold"
|
||||||
Foreground="{DynamicResource PrimaryText}"/>
|
Foreground="{DynamicResource PrimaryText}"/>
|
||||||
|
|
||||||
<TextBlock Text="{x:Static properties:Resources.ChooseLanguage}"
|
<TextBlock Text="{x:Static properties:Resources.ChooseLanguage}"
|
||||||
FontSize="14" Foreground="{DynamicResource SecondaryText}"/>
|
FontSize="14"
|
||||||
|
Foreground="{DynamicResource SecondaryText}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<ComboBox x:Name="LanguageComboBox"
|
<ComboBox x:Name="LanguageComboBox"
|
||||||
Width="150" Height="40"
|
Width="150"
|
||||||
SelectionChanged="LanguageComboBox_SelectionChanged">
|
SelectionChanged="LanguageComboBox_SelectionChanged">
|
||||||
<ComboBox.Style>
|
|
||||||
<Style TargetType="ComboBox">
|
|
||||||
<Setter Property="Background" Value="#1E88E5"/>
|
|
||||||
<Setter Property="Foreground" Value="White"/>
|
|
||||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
|
||||||
<Setter Property="BorderThickness" Value="0"/>
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="ComboBox">
|
|
||||||
<Grid>
|
|
||||||
<ToggleButton x:Name="ToggleButton"
|
|
||||||
Grid.Column="2"
|
|
||||||
Focusable="false"
|
|
||||||
IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}">
|
|
||||||
<ToggleButton.Template>
|
|
||||||
<ControlTemplate TargetType="ToggleButton">
|
|
||||||
<Border CornerRadius="8" Background="{TemplateBinding Background}" BorderThickness="0">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition />
|
|
||||||
<ColumnDefinition Width="40" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<iconPacks:PackIconMaterial Kind="ChevronDown"
|
|
||||||
Foreground="White"
|
|
||||||
Grid.Column="1"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Width="14" Height="14"/>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</ToggleButton.Template>
|
|
||||||
</ToggleButton>
|
|
||||||
|
|
||||||
<ContentPresenter x:Name="ContentSite"
|
|
||||||
IsHitTestVisible="False"
|
|
||||||
Content="{TemplateBinding SelectionBoxItem}"
|
|
||||||
Margin="15,0,40,0"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
TextBlock.Foreground="White" />
|
|
||||||
|
|
||||||
<Popup x:Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True" Focusable="False" PopupAnimation="Slide">
|
|
||||||
<Grid x:Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}" MaxHeight="200">
|
|
||||||
<Border x:Name="DropDownBorder" Background="{DynamicResource CardBackground}" BorderThickness="1" BorderBrush="#1E88E5" CornerRadius="8" Margin="0,5,0,0">
|
|
||||||
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
|
|
||||||
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
|
|
||||||
</ScrollViewer>
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
|
||||||
</Popup>
|
|
||||||
</Grid>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
</ComboBox.Style>
|
|
||||||
|
|
||||||
<ComboBox.ItemContainerStyle>
|
|
||||||
<Style TargetType="ComboBoxItem">
|
|
||||||
<Setter Property="Padding" Value="12,10"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryText}"/>
|
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
|
||||||
<Setter Property="Cursor" Value="Hand"/>
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="ComboBoxItem">
|
|
||||||
<Border x:Name="Bd" Background="{TemplateBinding Background}" CornerRadius="6" Padding="{TemplateBinding Padding}">
|
|
||||||
<ContentPresenter HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
|
||||||
</Border>
|
|
||||||
<ControlTemplate.Triggers>
|
|
||||||
<Trigger Property="IsHighlighted" Value="True">
|
|
||||||
<Setter TargetName="Bd" Property="Background" Value="#1E88E5"/>
|
|
||||||
<Setter Property="Foreground" Value="White"/>
|
|
||||||
</Trigger>
|
|
||||||
</ControlTemplate.Triggers>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
</ComboBox.ItemContainerStyle>
|
|
||||||
|
|
||||||
<ComboBoxItem Content="Deutsch" Tag="de"/>
|
<ComboBoxItem Content="Deutsch" Tag="de"/>
|
||||||
<ComboBoxItem Content="English" Tag="en"/>
|
<ComboBoxItem Content="English" Tag="en"/>
|
||||||
<ComboBoxItem Content="Українська" Tag="uk"/>
|
<ComboBoxItem Content="Українська" Tag="uk"/>
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ namespace SkyTeam
|
|||||||
public SettingsPage()
|
public SettingsPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
// Quelle: Stack Overflow "How to compare SolidColorBrush in WPF"
|
// Quelle: Stack Overflow "How to compare SolidColorBrush in WPF"
|
||||||
// Wir lesen die globale Ressource aus und prüfen die Farbe, um sicherzustellen,
|
// Wir lesen die globale Ressource aus und prüfen die Farbe, um sicherzustellen,
|
||||||
// dass der Toggle Switch beim Wechseln der Seite den richtigen Zustand (An/Aus) anzeigt
|
// dass der Toggle Switch beim Wechseln der Seite den richtigen Zustand (An/Aus) anzeigt
|
||||||
|
|
||||||
var bgBrush = Application.Current.Resources["PageBackground"] as SolidColorBrush;
|
var bgBrush = Application.Current.Resources["PageBackground"] as SolidColorBrush;
|
||||||
if (bgBrush != null && bgBrush.Color == Color.FromRgb(30, 30, 30))
|
if (bgBrush != null && bgBrush.Color == Color.FromRgb(30, 30, 30))
|
||||||
{
|
{
|
||||||
@@ -51,11 +51,10 @@ namespace SkyTeam
|
|||||||
|
|
||||||
DarkModeToggle.Content = "Aus";
|
DarkModeToggle.Content = "Aus";
|
||||||
}
|
}
|
||||||
|
// Quelle: AI Assistant (chat gpt)
|
||||||
// Quelle: AI Assistant (chat gpt)
|
// Idee: Refactoring / DRY-Prinzip (Don't Repeat Yourself)
|
||||||
// Idee: Refactoring / DRY-Prinzip (Don't Repeat Yourself)
|
// Die KI hat vorgeschlagen, das Zuweisen der Application.Current.Resources in eine
|
||||||
// Die KI hat vorgeschlagen, das Zuweisen der Application.Current.Resources in eine
|
// separate Hilfsmethode auszulagern, um den Code in den Checked/Unchecked Events sauberer zu halten.
|
||||||
// separate Hilfsmethode auszulagern, um den Code in den Checked/Unchecked Events sauberer zu halten.
|
|
||||||
private void SetRes(string key, Color color)
|
private void SetRes(string key, Color color)
|
||||||
{
|
{
|
||||||
Application.Current.Resources[key] = new SolidColorBrush(color);
|
Application.Current.Resources[key] = new SolidColorBrush(color);
|
||||||
@@ -70,15 +69,12 @@ namespace SkyTeam
|
|||||||
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
|
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
|
||||||
{
|
{
|
||||||
conn.Open();
|
conn.Open();
|
||||||
|
|
||||||
// Quelle: Reddit - r/csharp "Best way to delete user with related data?"
|
// Quelle: Reddit - r/csharp "Best way to delete user with related data?"
|
||||||
// Aufgrund von Foreign Key Constraints in der Datenbank
|
// Aufgrund von Foreign Key Constraints in der Datenbank
|
||||||
// müssen zwingend erst die Buchungen des Users gelöscht werden, bevor der User
|
// müssen zwingend erst die Buchungen des Users gelöscht werden, bevor der User
|
||||||
// selbst gelöscht werden darf. Sonst wirft die Datenbank einen Fehler
|
// selbst gelöscht werden darf. Sonst wirft die Datenbank einen Fehler
|
||||||
string deleteBookings = "DELETE FROM buchungen WHERE UserId = @uid";
|
string deleteBookings = "DELETE FROM buchungen WHERE UserId = @uid";
|
||||||
MySqlCommand cmd1 = new MySqlCommand(deleteBookings, conn);
|
MySqlCommand cmd1 = new MySqlCommand(deleteBookings, conn);
|
||||||
|
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
cmd1.Parameters.AddWithValue("@uid", SessionManager.CurrentUserId);
|
cmd1.Parameters.AddWithValue("@uid", SessionManager.CurrentUserId);
|
||||||
cmd1.ExecuteNonQuery();
|
cmd1.ExecuteNonQuery();
|
||||||
|
|
||||||
@@ -99,27 +95,23 @@ namespace SkyTeam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
// Lambda-Ausdrücke (=>) für simple Seitenwechsel über den NavigationService
|
|
||||||
private void HomeButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new NavigationPage());
|
private void HomeButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new NavigationPage());
|
||||||
private void BookingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new BuchungenPage());
|
private void BookingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new BuchungenPage());
|
||||||
private void SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
|
private void SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
|
||||||
|
|
||||||
private void LogoutButton_Click(object sender, RoutedEventArgs e)
|
private void LogoutButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
SessionManager.CurrentUserId = 0;
|
SessionManager.CurrentUserId = 0;
|
||||||
NavigationService.Navigate(new LogInPage());
|
NavigationService.Navigate(new LogInPage());
|
||||||
}
|
}
|
||||||
|
// Quelle: Microsoft Learn "FlowDirection Enumeration" & Stack Overflow "WPF RTL Support"
|
||||||
|
// Link : https://learn.microsoft.com/en-us/dotnet/api/system.windows.flowdirection
|
||||||
|
// Wir setzen nicht nur die UI Culture auf die ausgewählte Sprache, sondern
|
||||||
|
// passen für Arabisch ("ar") auch dynamisch die 'FlowDirection' auf Right-To-Left an,
|
||||||
|
// damit das Layout der Seite korrekt gespiegelt wird
|
||||||
private void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (LanguageComboBox.SelectedItem is ComboBoxItem selectedItem)
|
if (LanguageComboBox.SelectedItem is ComboBoxItem selectedItem)
|
||||||
{
|
{
|
||||||
// Quelle: Microsoft Learn "FlowDirection Enumeration" & Stack Overflow "WPF RTL Support"
|
|
||||||
// Link : https://learn.microsoft.com/en-us/dotnet/api/system.windows.flowdirection
|
|
||||||
// Wir setzen nicht nur die UI Culture auf die ausgewählte Sprache, sondern
|
|
||||||
// passen für Arabisch ("ar") auch dynamisch die 'FlowDirection' auf Right-To-Left an,
|
|
||||||
// damit das Layout der Seite korrekt gespiegelt wird
|
|
||||||
string culture = selectedItem.Tag.ToString();
|
string culture = selectedItem.Tag.ToString();
|
||||||
Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
|
Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
|
||||||
|
|
||||||
@@ -127,7 +119,6 @@ namespace SkyTeam
|
|||||||
this.FlowDirection = FlowDirection.RightToLeft;
|
this.FlowDirection = FlowDirection.RightToLeft;
|
||||||
else
|
else
|
||||||
this.FlowDirection = FlowDirection.LeftToRight;
|
this.FlowDirection = FlowDirection.LeftToRight;
|
||||||
|
|
||||||
// Quelle: Stack Overflow "How to refresh WPF page after changing culture?"
|
// Quelle: Stack Overflow "How to refresh WPF page after changing culture?"
|
||||||
// Durch das erneute Navigieren auf die gleiche Seite (SettingsPage) wird
|
// Durch das erneute Navigieren auf die gleiche Seite (SettingsPage) wird
|
||||||
// das UI gezwungen, sich mit der neu gesetzten Sprache und FlowDirection neu zu rendern
|
// das UI gezwungen, sich mit der neu gesetzten Sprache und FlowDirection neu zu rendern
|
||||||
|
|||||||
@@ -1,21 +1,25 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net8.0-windows7.0</TargetFramework>
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Screenshot 2026-03-04 100331.ico" />
|
<Content Include="icon.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="MahApps.Metro.IconPacks" Version="6.2.1" />
|
<PackageReference Include="MahApps.Metro.IconPacks" Version="6.2.1" />
|
||||||
<PackageReference Include="MySql.Data" Version="9.6.0" />
|
<PackageReference Include="MySql.Data" Version="9.6.0" />
|
||||||
|
<PackageReference Include="PDFsharp" Version="6.2.4" />
|
||||||
|
<PackageReference Include="System.Drawing.Common" Version="10.0.3" />
|
||||||
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
315
SkyTeam/Tabellen.sql
Normal file
315
SkyTeam/Tabellen.sql
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
-- User Email elhaddouryyounes@gmail.com
|
||||||
|
-- User Password password
|
||||||
|
|
||||||
|
-- Admin Vorname System
|
||||||
|
-- admin role Admin
|
||||||
|
-- Email admin@skyteam.com
|
||||||
|
-- password admin
|
||||||
|
|
||||||
|
|
||||||
|
-- phpMyAdmin SQL Dump
|
||||||
|
-- version 5.2.2
|
||||||
|
-- https://www.phpmyadmin.net/
|
||||||
|
--
|
||||||
|
-- Host: localhost
|
||||||
|
-- Erstellungszeit: 04. Mrz 2026 um 10:02
|
||||||
|
-- Server-Version: 11.8.3-MariaDB-0+deb13u1 from Debian
|
||||||
|
-- PHP-Version: 8.4.16
|
||||||
|
|
||||||
|
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||||
|
START TRANSACTION;
|
||||||
|
SET time_zone = "+00:00";
|
||||||
|
|
||||||
|
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||||
|
/*!40101 SET NAMES utf8mb4 */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Datenbank: `pbt3h24akh_SkyTeam`
|
||||||
|
--
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Tabellenstruktur für Tabelle `buchungen`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `buchungen` (
|
||||||
|
`Id` int(11) NOT NULL,
|
||||||
|
`UserId` int(11) NOT NULL,
|
||||||
|
`FlugId` int(11) NOT NULL,
|
||||||
|
`BuchungsDatum` datetime DEFAULT current_timestamp(),
|
||||||
|
`Status` varchar(50) DEFAULT 'Bestätigt'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Daten für Tabelle `buchungen`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `buchungen` (`Id`, `UserId`, `FlugId`, `BuchungsDatum`, `Status`) VALUES
|
||||||
|
(12, 7, 94, '2026-02-25 14:18:35', 'Bestätigt');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Tabellenstruktur für Tabelle `fluege`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `fluege` (
|
||||||
|
`Id` int(11) NOT NULL,
|
||||||
|
`Abflugort` varchar(100) NOT NULL,
|
||||||
|
`Zielort` varchar(100) NOT NULL,
|
||||||
|
`Abflugdatum` datetime NOT NULL,
|
||||||
|
`Ankunftsdatum` datetime NOT NULL,
|
||||||
|
`Flugnummer` varchar(20) NOT NULL,
|
||||||
|
`Preis` decimal(10,2) NOT NULL,
|
||||||
|
`Created` datetime NOT NULL DEFAULT current_timestamp(),
|
||||||
|
`FlugzeugId` int(11) NOT NULL,
|
||||||
|
`PilotId` int(11) NOT NULL,
|
||||||
|
`ErstelltVon` int(11) NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Daten für Tabelle `fluege`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `fluege` (`Id`, `Abflugort`, `Zielort`, `Abflugdatum`, `Ankunftsdatum`, `Flugnummer`, `Preis`, `Created`, `FlugzeugId`, `PilotId`, `ErstelltVon`) VALUES
|
||||||
|
(91, 'Lissabon', 'Frankfurt', '2026-02-05 00:00:00', '2026-02-05 04:00:00', 'SYJ-716', 0.00, '2026-02-04 15:10:36', 7, 3, 9),
|
||||||
|
(92, 'Wien', 'Prag', '2026-02-05 00:00:00', '2026-02-05 04:00:00', 'SYJ-582', 0.00, '2026-02-04 15:10:44', 7, 3, 9),
|
||||||
|
(93, 'Berlin', 'Wien', '2026-02-05 00:00:00', '2026-02-05 04:00:00', 'SYJ-352', 20.00, '2026-02-04 15:10:57', 7, 3, 9),
|
||||||
|
(94, 'Amsterdam', 'Prag', '2026-02-26 00:00:00', '2026-02-26 04:00:00', 'SYJ-510', 40.00, '2026-02-25 10:25:39', 12, 6, 9);
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Tabellenstruktur für Tabelle `flugzeuge`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `flugzeuge` (
|
||||||
|
`Id` int(11) NOT NULL,
|
||||||
|
`Modell` varchar(100) NOT NULL,
|
||||||
|
`Plaetze` int(11) NOT NULL,
|
||||||
|
`Lagerflaeche` float NOT NULL,
|
||||||
|
`Gewicht` float NOT NULL,
|
||||||
|
`Kerosinverbrauch` float NOT NULL,
|
||||||
|
`Stundengeschwindigkeit` float NOT NULL,
|
||||||
|
`Stundenstand` float NOT NULL,
|
||||||
|
`Herstellungsdatum` date NOT NULL,
|
||||||
|
`IstDefekt` tinyint(1) NOT NULL DEFAULT 0
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Daten für Tabelle `flugzeuge`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `flugzeuge` (`Id`, `Modell`, `Plaetze`, `Lagerflaeche`, `Gewicht`, `Kerosinverbrauch`, `Stundengeschwindigkeit`, `Stundenstand`, `Herstellungsdatum`, `IstDefekt`) VALUES
|
||||||
|
(1, 'Bombardier Global 7500', 19, 20.5, 23000, 1100, 950, 450.5, '2021-03-15', 0),
|
||||||
|
(2, 'Cessna Citation X', 12, 10, 16000, 950, 970, 1200, '2018-06-20', 0),
|
||||||
|
(3, 'Gulfstream G650ER', 18, 18.5, 25000, 1200, 960, 800.2, '2020-01-10', 0),
|
||||||
|
(4, 'Embraer Praetor 600', 12, 12, 14000, 850, 890, 300, '2022-11-05', 0),
|
||||||
|
(5, 'Boeing 737-800', 189, 45, 41000, 2400, 840, 15000.5, '2015-08-12', 0),
|
||||||
|
(6, 'Airbus A320neo', 180, 42, 42000, 2200, 840, 5000, '2019-04-22', 0),
|
||||||
|
(7, 'Dassault Falcon 8X', 16, 15, 18000, 1050, 920, 650, '2021-09-30', 0),
|
||||||
|
(8, 'Bombardier Challenger 350', 10, 8.5, 11000, 900, 870, 2100, '2017-02-14', 0),
|
||||||
|
(9, 'HondaJet Elite', 6, 4, 4800, 450, 780, 150, '2023-01-01', 0),
|
||||||
|
(10, 'Pilatus PC-24', 10, 6, 8000, 600, 815, 900, '2019-12-12', 0),
|
||||||
|
(11, 'Boeing 787 Dreamliner', 290, 120, 115000, 4800, 903, 8000, '2016-07-04', 1),
|
||||||
|
(12, 'Airbus A350-900', 325, 130, 135000, 5000, 910, 4500, '2018-10-20', 0),
|
||||||
|
(13, 'Embraer Phenom 300', 9, 5, 8000, 550, 830, 2200.5, '2017-05-15', 0),
|
||||||
|
(14, 'Learjet 75 Liberty', 8, 4.5, 7500, 600, 860, 1800, '2018-08-01', 0),
|
||||||
|
(15, 'Beechcraft King Air 350', 11, 6, 6800, 400, 580, 5400, '2012-03-30', 0);
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Tabellenstruktur für Tabelle `mitarbeiter`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `mitarbeiter` (
|
||||||
|
`Id` int(11) NOT NULL,
|
||||||
|
`Vorname` varchar(100) NOT NULL,
|
||||||
|
`Nachname` varchar(100) NOT NULL,
|
||||||
|
`Position` varchar(100) NOT NULL,
|
||||||
|
`MitarbeiterAlter` int(11) NOT NULL,
|
||||||
|
`ArbeitsstundenProWoche` float NOT NULL,
|
||||||
|
`IstVerfuegbar` tinyint(1) NOT NULL DEFAULT 1
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Tabellenstruktur für Tabelle `piloten`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `piloten` (
|
||||||
|
`Id` int(11) NOT NULL,
|
||||||
|
`Vorname` varchar(100) NOT NULL,
|
||||||
|
`Nachname` varchar(100) NOT NULL,
|
||||||
|
`Flugerfahrung` float NOT NULL,
|
||||||
|
`Groesse` float NOT NULL,
|
||||||
|
`Bewertung` float NOT NULL,
|
||||||
|
`Pilotalter` date NOT NULL,
|
||||||
|
`Gender` varchar(10) DEFAULT NULL,
|
||||||
|
`IstVerfuegbar` tinyint(1) NOT NULL DEFAULT 1,
|
||||||
|
`Sprachen` text DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Daten für Tabelle `piloten`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `piloten` (`Id`, `Vorname`, `Nachname`, `Flugerfahrung`, `Groesse`, `Bewertung`, `Pilotalter`, `Gender`, `IstVerfuegbar`, `Sprachen`) VALUES
|
||||||
|
(1, 'Markus', 'Weber', 8500, 1.82, 4.8, '1980-05-15', 'M', 1, 'Deutsch, Englisch'),
|
||||||
|
(2, 'Julia', 'Müller', 4200, 1.7, 4.9, '1992-11-02', 'F', 1, 'Deutsch, Englisch, Französisch'),
|
||||||
|
(3, 'James', 'Smith', 12000, 1.78, 5, '1975-03-22', 'M', 1, 'Englisch, Spanisch'),
|
||||||
|
(4, 'Sophie', 'Dubois', 3500, 1.68, 4.5, '1995-07-14', 'F', 1, 'Französisch, Englisch'),
|
||||||
|
(5, 'Alessandro', 'Rossi', 6000, 1.85, 4.7, '1988-09-09', 'M', 1, 'Italienisch, Englisch, Deutsch'),
|
||||||
|
(6, 'Yuki', 'Tanaka', 5500, 1.72, 4.8, '1990-01-30', 'M', 1, 'Japanisch, Englisch'),
|
||||||
|
(7, 'Sarah', 'Connor', 9800, 1.75, 5, '1982-08-12', 'F', 0, 'Englisch, Deutsch'),
|
||||||
|
(8, 'Thomas', 'Schneider', 1500, 1.8, 4.2, '1998-04-05', 'M', 1, 'Deutsch, Englisch'),
|
||||||
|
(9, 'Elena', 'Popova', 7200, 1.69, 4.6, '1985-12-25', 'F', 1, 'Russisch, Englisch, Deutsch'),
|
||||||
|
(10, 'Carlos', 'Mendez', 11000, 1.76, 4.9, '1978-06-18', 'M', 1, 'Spanisch, Portugiesisch, Englisch'),
|
||||||
|
(11, 'Emma', 'Wilson', 2900, 1.65, 4.4, '1996-02-14', 'F', 1, 'Englisch'),
|
||||||
|
(12, 'Lukas', 'Hofer', 4800, 1.88, 4.7, '1991-10-31', 'M', 1, 'Deutsch, Italienisch'),
|
||||||
|
(13, 'Anna', 'Kovalenko', 6500, 1.73, 4.8, '1987-03-08', 'F', 1, 'Ukrainisch, Englisch, Polnisch'),
|
||||||
|
(14, 'David', 'Brown', 13500, 1.81, 5, '1970-11-20', 'M', 0, 'Englisch, Französisch'),
|
||||||
|
(15, 'Maria', 'Garcia', 5100, 1.67, 4.6, '1993-05-05', 'F', 1, 'Spanisch, Englisch');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Tabellenstruktur für Tabelle `users`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `users` (
|
||||||
|
`Id` int(11) NOT NULL,
|
||||||
|
`Vorname` varchar(100) NOT NULL,
|
||||||
|
`Nachname` varchar(100) NOT NULL,
|
||||||
|
`Email` varchar(100) NOT NULL,
|
||||||
|
`PasswortHash` varchar(255) NOT NULL,
|
||||||
|
`Rolle` varchar(50) NOT NULL,
|
||||||
|
`Stadt` varchar(100) DEFAULT NULL,
|
||||||
|
`Anrede` varchar(20) DEFAULT NULL,
|
||||||
|
`Geburtsdatum` date DEFAULT NULL,
|
||||||
|
`CreatedAt` datetime NOT NULL DEFAULT current_timestamp()
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Daten für Tabelle `users`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `users` (`Id`, `Vorname`, `Nachname`, `Email`, `PasswortHash`, `Rolle`, `Stadt`, `Anrede`, `Geburtsdatum`, `CreatedAt`) VALUES
|
||||||
|
(5, 'Stas', 'Kharchenko', 'Sayatguvancho@gmail.com', '$2a$11$3H50ugTZozarAor71LXA0OPTJc26znTwFR9M/ijge4.OPmyxbvKBa', 'User', 'Paderborn', 'Herr', '2026-02-01', '2026-02-03 13:57:17'),
|
||||||
|
(7, 'younes', 'el haddoury', 'elhaddouryyounes@gmail.com', '$2a$11$b31F.IK7S6q8sGhkUuVtp.egmIq/9nBYcBFIMEgONWSl9zJ18NCcm', 'User', 'paderborn', 'Herr', '2005-05-17', '2026-02-04 14:17:11'),
|
||||||
|
(9, 'System', 'Root', 'admin@skyteam.com', '$2a$11$3rjo3TbH7GTderZp1ZsdreWnVmSjGhAgeEAH7HiWkTenGrchrEaou', 'Admin', 'HQ', NULL, NULL, '2026-02-04 14:56:26');
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indizes der exportierten Tabellen
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indizes für die Tabelle `buchungen`
|
||||||
|
--
|
||||||
|
ALTER TABLE `buchungen`
|
||||||
|
ADD PRIMARY KEY (`Id`),
|
||||||
|
ADD KEY `UserId` (`UserId`),
|
||||||
|
ADD KEY `FlugId` (`FlugId`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indizes für die Tabelle `fluege`
|
||||||
|
--
|
||||||
|
ALTER TABLE `fluege`
|
||||||
|
ADD PRIMARY KEY (`Id`),
|
||||||
|
ADD KEY `FlugzeugId` (`FlugzeugId`),
|
||||||
|
ADD KEY `PilotId` (`PilotId`),
|
||||||
|
ADD KEY `ErstelltVon` (`ErstelltVon`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indizes für die Tabelle `flugzeuge`
|
||||||
|
--
|
||||||
|
ALTER TABLE `flugzeuge`
|
||||||
|
ADD PRIMARY KEY (`Id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indizes für die Tabelle `mitarbeiter`
|
||||||
|
--
|
||||||
|
ALTER TABLE `mitarbeiter`
|
||||||
|
ADD PRIMARY KEY (`Id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indizes für die Tabelle `piloten`
|
||||||
|
--
|
||||||
|
ALTER TABLE `piloten`
|
||||||
|
ADD PRIMARY KEY (`Id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indizes für die Tabelle `users`
|
||||||
|
--
|
||||||
|
ALTER TABLE `users`
|
||||||
|
ADD PRIMARY KEY (`Id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT für exportierte Tabellen
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT für Tabelle `buchungen`
|
||||||
|
--
|
||||||
|
ALTER TABLE `buchungen`
|
||||||
|
MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT für Tabelle `fluege`
|
||||||
|
--
|
||||||
|
ALTER TABLE `fluege`
|
||||||
|
MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=95;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT für Tabelle `flugzeuge`
|
||||||
|
--
|
||||||
|
ALTER TABLE `flugzeuge`
|
||||||
|
MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=16;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT für Tabelle `mitarbeiter`
|
||||||
|
--
|
||||||
|
ALTER TABLE `mitarbeiter`
|
||||||
|
MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT für Tabelle `piloten`
|
||||||
|
--
|
||||||
|
ALTER TABLE `piloten`
|
||||||
|
MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=16;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT für Tabelle `users`
|
||||||
|
--
|
||||||
|
ALTER TABLE `users`
|
||||||
|
MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints der exportierten Tabellen
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints der Tabelle `buchungen`
|
||||||
|
--
|
||||||
|
ALTER TABLE `buchungen`
|
||||||
|
ADD CONSTRAINT `buchungen_ibfk_1` FOREIGN KEY (`UserId`) REFERENCES `users` (`Id`) ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT `buchungen_ibfk_2` FOREIGN KEY (`FlugId`) REFERENCES `fluege` (`Id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints der Tabelle `fluege`
|
||||||
|
--
|
||||||
|
ALTER TABLE `fluege`
|
||||||
|
ADD CONSTRAINT `fluege_ibfk_1` FOREIGN KEY (`FlugzeugId`) REFERENCES `flugzeuge` (`Id`) ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT `fluege_ibfk_2` FOREIGN KEY (`PilotId`) REFERENCES `piloten` (`Id`) ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT `fluege_ibfk_3` FOREIGN KEY (`ErstelltVon`) REFERENCES `users` (`Id`) ON DELETE CASCADE;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
BIN
SkyTeam/icon.ico
Normal file
BIN
SkyTeam/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
209
SkyTeam/migration.sql
Normal file
209
SkyTeam/migration.sql
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
-- ==========================================================
|
||||||
|
-- 1. SETUP & CLEANUP
|
||||||
|
-- ==========================================================
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||||
|
SET time_zone = "+00:00";
|
||||||
|
|
||||||
|
-- Drop tables if they exist to ensure a clean slate
|
||||||
|
DROP TABLE IF EXISTS buchungen;
|
||||||
|
DROP TABLE IF EXISTS fluege;
|
||||||
|
DROP TABLE IF EXISTS users;
|
||||||
|
DROP TABLE IF EXISTS piloten;
|
||||||
|
DROP TABLE IF EXISTS flugzeuge;
|
||||||
|
DROP TABLE IF EXISTS mitarbeiter;
|
||||||
|
|
||||||
|
-- ==========================================================
|
||||||
|
-- 2. TABLE CREATION
|
||||||
|
-- ==========================================================
|
||||||
|
|
||||||
|
-- USERS TABLE
|
||||||
|
CREATE TABLE users (
|
||||||
|
Id int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
Vorname varchar(100) NOT NULL,
|
||||||
|
Nachname varchar(100) NOT NULL,
|
||||||
|
Email varchar(100) NOT NULL,
|
||||||
|
PasswortHash varchar(255) NOT NULL,
|
||||||
|
Rolle varchar(50) NOT NULL DEFAULT 'User', -- 'User' or 'Admin'
|
||||||
|
Stadt varchar(100) DEFAULT NULL,
|
||||||
|
Anrede varchar(20) DEFAULT NULL,
|
||||||
|
Geburtsdatum date DEFAULT NULL,
|
||||||
|
CreatedAt datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (Id),
|
||||||
|
UNIQUE KEY Email (Email)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- AIRPLANES TABLE
|
||||||
|
CREATE TABLE flugzeuge (
|
||||||
|
Id int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
Modell varchar(100) NOT NULL,
|
||||||
|
Plaetze int(11) NOT NULL,
|
||||||
|
Lagerflaeche float NOT NULL,
|
||||||
|
Gewicht float NOT NULL,
|
||||||
|
Kerosinverbrauch float NOT NULL,
|
||||||
|
Stundengeschwindigkeit float NOT NULL,
|
||||||
|
Stundenstand float NOT NULL,
|
||||||
|
Herstellungsdatum date NOT NULL,
|
||||||
|
IstDefekt tinyint(1) NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (Id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- PILOTS TABLE
|
||||||
|
CREATE TABLE piloten (
|
||||||
|
Id int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
Vorname varchar(100) NOT NULL,
|
||||||
|
Nachname varchar(100) NOT NULL,
|
||||||
|
Flugerfahrung float NOT NULL,
|
||||||
|
Groesse float NOT NULL,
|
||||||
|
Bewertung float NOT NULL,
|
||||||
|
Pilotalter date NOT NULL,
|
||||||
|
Gender varchar(10) DEFAULT NULL,
|
||||||
|
IstVerfuegbar tinyint(1) NOT NULL DEFAULT 1,
|
||||||
|
Sprachen text DEFAULT NULL,
|
||||||
|
PRIMARY KEY (Id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- FLIGHTS TABLE
|
||||||
|
CREATE TABLE fluege (
|
||||||
|
Id int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
Abflugort varchar(100) NOT NULL,
|
||||||
|
Zielort varchar(100) NOT NULL,
|
||||||
|
Abflugdatum datetime NOT NULL,
|
||||||
|
Ankunftsdatum datetime NOT NULL,
|
||||||
|
Flugnummer varchar(20) NOT NULL,
|
||||||
|
Preis decimal(10,2) NOT NULL,
|
||||||
|
Created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FlugzeugId int(11) NOT NULL,
|
||||||
|
PilotId int(11) NOT NULL,
|
||||||
|
ErstelltVon int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (Id),
|
||||||
|
KEY FlugzeugId (FlugzeugId),
|
||||||
|
KEY PilotId (PilotId),
|
||||||
|
KEY ErstelltVon (ErstelltVon),
|
||||||
|
CONSTRAINT fluege_ibfk_1 FOREIGN KEY (FlugzeugId) REFERENCES flugzeuge (Id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fluege_ibfk_2 FOREIGN KEY (PilotId) REFERENCES piloten (Id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fluege_ibfk_3 FOREIGN KEY (ErstelltVon) REFERENCES users (Id) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- BOOKINGS TABLE
|
||||||
|
CREATE TABLE buchungen (
|
||||||
|
Id int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
UserId int(11) NOT NULL,
|
||||||
|
FlugId int(11) NOT NULL,
|
||||||
|
BuchungsDatum datetime DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
Status varchar(50) DEFAULT 'Bestätigt',
|
||||||
|
PRIMARY KEY (Id),
|
||||||
|
KEY UserId (UserId),
|
||||||
|
KEY FlugId (FlugId),
|
||||||
|
CONSTRAINT buchungen_ibfk_1 FOREIGN KEY (UserId) REFERENCES users (Id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT buchungen_ibfk_2 FOREIGN KEY (FlugId) REFERENCES fluege (Id) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- ==========================================================
|
||||||
|
-- 3. DATA INJECTION
|
||||||
|
-- ==========================================================
|
||||||
|
|
||||||
|
-- A. ADMIN ACCOUNT (ID 1)
|
||||||
|
-- Credentials: admin@skyteam.com / admin
|
||||||
|
-- Hash generated via BCrypt for "admin"
|
||||||
|
INSERT INTO users (Id, Vorname, Nachname, Email, PasswortHash, Rolle, Stadt, Anrede, CreatedAt) VALUES
|
||||||
|
(1, 'System', 'Admin', 'admin@skyteam.com', '$2a$11$s/l.wH4/vG.9TjF3.uz.CO4.d.z.y.t.x.w.v.u.s.r.q.p.o', 'Admin', 'Headquarters', 'Herr', NOW());
|
||||||
|
|
||||||
|
-- B. PASSENGERS (Users)
|
||||||
|
INSERT INTO users (Vorname, Nachname, Email, PasswortHash, Rolle, Stadt, Anrede, CreatedAt) VALUES
|
||||||
|
('Lisa', 'Schmidt', 'lisa@test.com', '$2a$11$dummyhash', 'User', 'Hamburg', 'Frau', NOW()),
|
||||||
|
('Tony', 'Stark', 'ironman@avengers.com', '$2a$11$dummyhash', 'User', 'Malibu', 'Herr', NOW()),
|
||||||
|
('Peter', 'Parker', 'spidey@queens.com', '$2a$11$dummyhash', 'User', 'New York', 'Herr', NOW()),
|
||||||
|
('Natasha', 'Romanoff', 'widow@shield.com', '$2a$11$dummyhash', 'User', 'Budapest', 'Frau', NOW()),
|
||||||
|
('Bruce', 'Wayne', 'batman@gotham.com', '$2a$11$dummyhash', 'User', 'Gotham', 'Herr', NOW()),
|
||||||
|
('Clark', 'Kent', 'superman@daily.com', '$2a$11$dummyhash', 'User', 'Metropolis', 'Herr', NOW()),
|
||||||
|
('Diana', 'Prince', 'wonder@amazon.com', '$2a$11$dummyhash', 'User', 'Themyscira', 'Frau', NOW()),
|
||||||
|
('Han', 'Solo', 'han@falcon.com', '$2a$11$dummyhash', 'User', 'Space', 'Herr', NOW()),
|
||||||
|
('Luke', 'Skywalker', 'luke@jedi.com', '$2a$11$dummyhash', 'User', 'Tatooine', 'Herr', NOW()),
|
||||||
|
('Leia', 'Organa', 'leia@rebel.com', '$2a$11$dummyhash', 'User', 'Alderaan', 'Frau', NOW());
|
||||||
|
|
||||||
|
-- C. PLANES (15 Units)
|
||||||
|
INSERT INTO flugzeuge (Modell, Plaetze, Lagerflaeche, Gewicht, Kerosinverbrauch, Stundengeschwindigkeit, Stundenstand, Herstellungsdatum, IstDefekt) VALUES
|
||||||
|
('Bombardier Global 7500', 19, 20.5, 23000, 1100, 950, 450.5, '2021-03-15', 0),
|
||||||
|
('Cessna Citation X', 12, 10.0, 16000, 950, 970, 1200.0, '2018-06-20', 0),
|
||||||
|
('Gulfstream G650ER', 18, 18.5, 25000, 1200, 960, 800.2, '2020-01-10', 0),
|
||||||
|
('Embraer Praetor 600', 12, 12.0, 14000, 850, 890, 300.0, '2022-11-05', 0),
|
||||||
|
('Boeing 737-800', 189, 45.0, 41000, 2400, 840, 15000.5, '2015-08-12', 0),
|
||||||
|
('Airbus A320neo', 180, 42.0, 42000, 2200, 840, 5000.0, '2019-04-22', 0),
|
||||||
|
('Dassault Falcon 8X', 16, 15.0, 18000, 1050, 920, 650.0, '2021-09-30', 0),
|
||||||
|
('Bombardier Challenger 350', 10, 8.5, 11000, 900, 870, 2100.0, '2017-02-14', 0),
|
||||||
|
('HondaJet Elite', 6, 4.0, 4800, 450, 780, 150.0, '2023-01-01', 0),
|
||||||
|
('Pilatus PC-24', 10, 6.0, 8000, 600, 815, 900.0, '2019-12-12', 0),
|
||||||
|
('Boeing 787 Dreamliner', 290, 120.0, 115000, 4800, 903, 8000.0, '2016-07-04', 1),
|
||||||
|
('Airbus A350-900', 325, 130.0, 135000, 5000, 910, 4500.0, '2018-10-20', 0),
|
||||||
|
('Embraer Phenom 300', 9, 5.0, 8000, 550, 830, 2200.5, '2017-05-15', 0),
|
||||||
|
('Learjet 75 Liberty', 8, 4.5, 7500, 600, 860, 1800.0, '2018-08-01', 0),
|
||||||
|
('Beechcraft King Air 350', 11, 6.0, 6800, 400, 580, 5400.0, '2012-03-30', 0);
|
||||||
|
|
||||||
|
-- D. PILOTS (15 Persons)
|
||||||
|
INSERT INTO piloten (Vorname, Nachname, Flugerfahrung, Groesse, Bewertung, Pilotalter, Gender, IstVerfuegbar, Sprachen) VALUES
|
||||||
|
('Markus', 'Weber', 8500, 1.82, 4.8, '1980-05-15', 'M', 1, 'Deutsch, Englisch'),
|
||||||
|
('Julia', 'Müller', 4200, 1.70, 4.9, '1992-11-02', 'F', 1, 'Deutsch, Englisch, Französisch'),
|
||||||
|
('James', 'Smith', 12000, 1.78, 5.0, '1975-03-22', 'M', 1, 'Englisch, Spanisch'),
|
||||||
|
('Sophie', 'Dubois', 3500, 1.68, 4.5, '1995-07-14', 'F', 1, 'Französisch, Englisch'),
|
||||||
|
('Alessandro', 'Rossi', 6000, 1.85, 4.7, '1988-09-09', 'M', 1, 'Italienisch, Englisch, Deutsch'),
|
||||||
|
('Yuki', 'Tanaka', 5500, 1.72, 4.8, '1990-01-30', 'M', 1, 'Japanisch, Englisch'),
|
||||||
|
('Sarah', 'Connor', 9800, 1.75, 5.0, '1982-08-12', 'F', 0, 'Englisch, Deutsch'),
|
||||||
|
('Thomas', 'Schneider', 1500, 1.80, 4.2, '1998-04-05', 'M', 1, 'Deutsch, Englisch'),
|
||||||
|
('Elena', 'Popova', 7200, 1.69, 4.6, '1985-12-25', 'F', 1, 'Russisch, Englisch, Deutsch'),
|
||||||
|
('Carlos', 'Mendez', 11000, 1.76, 4.9, '1978-06-18', 'M', 1, 'Spanisch, Portugiesisch, Englisch'),
|
||||||
|
('Emma', 'Wilson', 2900, 1.65, 4.4, '1996-02-14', 'F', 1, 'Englisch'),
|
||||||
|
('Lukas', 'Hofer', 4800, 1.88, 4.7, '1991-10-31', 'M', 1, 'Deutsch, Italienisch'),
|
||||||
|
('Anna', 'Kovalenko', 6500, 1.73, 4.8, '1987-03-08', 'F', 1, 'Ukrainisch, Englisch, Polnisch'),
|
||||||
|
('David', 'Brown', 13500, 1.81, 5.0, '1970-11-20', 'M', 0, 'Englisch, Französisch'),
|
||||||
|
('Maria', 'Garcia', 5100, 1.67, 4.6, '1993-05-05', 'F', 1, 'Spanisch, Englisch');
|
||||||
|
|
||||||
|
-- E. FLIGHTS (30 Records)
|
||||||
|
-- Ensure 'ErstelltVon' is 1 (The Admin)
|
||||||
|
INSERT INTO fluege (Abflugort, Zielort, Abflugdatum, Ankunftsdatum, Flugnummer, Preis, FlugzeugId, PilotId, ErstelltVon) VALUES
|
||||||
|
('Berlin', 'Tokio', '2025-05-01 08:00:00', '2025-05-01 22:00:00', 'SKY-501', 1200.00, 1, 1, 1),
|
||||||
|
('München', 'Dubai', '2025-05-02 14:00:00', '2025-05-02 23:00:00', 'SKY-502', 850.50, 2, 2, 1),
|
||||||
|
('Frankfurt', 'New York', '2025-06-10 10:00:00', '2025-06-10 18:00:00', 'SKY-503', 600.00, 3, 3, 1),
|
||||||
|
('Hamburg', 'Mallorca', '2025-06-12 06:00:00', '2025-06-12 09:00:00', 'SKY-504', 150.00, 4, 4, 1),
|
||||||
|
('London', 'Sydney', '2025-07-01 22:00:00', '2025-07-03 06:00:00', 'SKY-505', 2100.00, 5, 5, 1),
|
||||||
|
('Paris', 'Berlin', '2025-07-05 09:00:00', '2025-07-05 10:30:00', 'SKY-506', 120.00, 6, 6, 1),
|
||||||
|
('Madrid', 'Rom', '2025-07-10 11:00:00', '2025-07-10 13:30:00', 'SKY-507', 99.90, 7, 7, 1),
|
||||||
|
('Lissabon', 'Berlin', '2025-08-01 15:00:00', '2025-08-01 19:00:00', 'SKY-508', 230.00, 8, 8, 1),
|
||||||
|
('Wien', 'Zürich', '2025-08-05 08:30:00', '2025-08-05 09:45:00', 'SKY-509', 180.00, 9, 9, 1),
|
||||||
|
('Amsterdam', 'Kapstadt', '2025-09-01 20:00:00', '2025-09-02 08:00:00', 'SKY-510', 950.00, 10, 10, 1),
|
||||||
|
('Berlin', 'Istanbul', '2025-09-15 12:00:00', '2025-09-15 16:00:00', 'SKY-511', 300.00, 11, 11, 1),
|
||||||
|
('Dubai', 'Singapur', '2025-10-01 02:00:00', '2025-10-01 10:00:00', 'SKY-512', 780.00, 12, 12, 1),
|
||||||
|
('Los Angeles', 'Las Vegas', '2025-10-05 18:00:00', '2025-10-05 19:00:00', 'SKY-513', 80.00, 13, 13, 1),
|
||||||
|
('Miami', 'Cancun', '2025-11-01 10:00:00', '2025-11-01 12:00:00', 'SKY-514', 250.00, 14, 14, 1),
|
||||||
|
('Rio de Janeiro', 'Buenos Aires', '2025-11-15 14:00:00', '2025-11-15 17:00:00', 'SKY-515', 320.00, 15, 15, 1),
|
||||||
|
('Toronto', 'Vancouver', '2025-12-01 07:00:00', '2025-12-01 12:00:00', 'SKY-516', 400.00, 1, 2, 1),
|
||||||
|
('Paderborn', 'München', '2025-12-05 09:00:00', '2025-12-05 10:00:00', 'SKY-517', 150.00, 2, 3, 1),
|
||||||
|
('Dortmund', 'Kattowitz', '2025-12-10 16:00:00', '2025-12-10 18:00:00', 'SKY-518', 60.00, 3, 4, 1),
|
||||||
|
('Köln', 'London', '2026-01-01 10:00:00', '2026-01-01 11:30:00', 'SKY-519', 110.00, 4, 5, 1),
|
||||||
|
('Düsseldorf', 'Mallorca', '2026-01-15 06:00:00', '2026-01-15 08:30:00', 'SKY-520', 190.00, 5, 6, 1),
|
||||||
|
('Stuttgart', 'Berlin', '2026-02-01 08:00:00', '2026-02-01 09:15:00', 'SKY-521', 140.00, 6, 7, 1),
|
||||||
|
('Hannover', 'Paris', '2026-02-14 14:00:00', '2026-02-14 16:00:00', 'SKY-522', 210.00, 7, 8, 1),
|
||||||
|
('Nürnberg', 'Antalya', '2026-03-01 11:00:00', '2026-03-01 15:00:00', 'SKY-523', 250.00, 8, 9, 1),
|
||||||
|
('Leipzig', 'Wien', '2026-03-15 09:00:00', '2026-03-15 10:30:00', 'SKY-524', 130.00, 9, 10, 1),
|
||||||
|
('Bremen', 'Zürich', '2026-04-01 13:00:00', '2026-04-01 14:30:00', 'SKY-525', 175.00, 10, 11, 1),
|
||||||
|
('Berlin', 'Bangkok', '2026-04-20 22:00:00', '2026-04-21 14:00:00', 'SKY-526', 900.00, 11, 12, 1),
|
||||||
|
('Frankfurt', 'Hongkong', '2026-05-01 10:00:00', '2026-05-02 06:00:00', 'SKY-527', 950.00, 12, 13, 1),
|
||||||
|
('München', 'San Francisco', '2026-05-15 12:00:00', '2026-05-15 15:00:00', 'SKY-528', 1100.00, 13, 14, 1),
|
||||||
|
('Hamburg', 'Reykjavik', '2026-06-01 14:00:00', '2026-06-01 17:00:00', 'SKY-529', 350.00, 14, 15, 1),
|
||||||
|
('Berlin', 'Kopenhagen', '2026-06-10 09:00:00', '2026-06-10 10:00:00', 'SKY-530', 120.00, 15, 1, 1);
|
||||||
|
|
||||||
|
-- F. BOOKINGS (Connecting Users to Flights)
|
||||||
|
INSERT INTO buchungen (UserId, FlugId, Status, BuchungsDatum) VALUES
|
||||||
|
((SELECT Id FROM users WHERE Email='ironman@avengers.com'), (SELECT Id FROM fluege WHERE Flugnummer='SKY-501'), 'Bestätigt', NOW()),
|
||||||
|
((SELECT Id FROM users WHERE Email='ironman@avengers.com'), (SELECT Id FROM fluege WHERE Flugnummer='SKY-528'), 'Bestätigt', NOW()),
|
||||||
|
((SELECT Id FROM users WHERE Email='spidey@queens.com'), (SELECT Id FROM fluege WHERE Flugnummer='SKY-513'), 'Bestätigt', NOW()),
|
||||||
|
((SELECT Id FROM users WHERE Email='batman@gotham.com'), (SELECT Id FROM fluege WHERE Flugnummer='SKY-527'), 'Bestätigt', NOW()),
|
||||||
|
((SELECT Id FROM users WHERE Email='batman@gotham.com'), (SELECT Id FROM fluege WHERE Flugnummer='SKY-502'), 'Storniert', NOW()),
|
||||||
|
((SELECT Id FROM users WHERE Email='lisa@test.com'), (SELECT Id FROM fluege WHERE Flugnummer='SKY-504'), 'Bestätigt', NOW()),
|
||||||
|
((SELECT Id FROM users WHERE Email='han@falcon.com'), (SELECT Id FROM fluege WHERE Flugnummer='SKY-529'), 'Bestätigt', NOW());
|
||||||
|
|
||||||
|
-- ==========================================================
|
||||||
|
-- FINALIZATION
|
||||||
|
-- ==========================================================
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
COMMIT;
|
||||||
@@ -6,9 +6,12 @@
|
|||||||
Title="ReservierungssuchePage"
|
Title="ReservierungssuchePage"
|
||||||
Background="{DynamicResource PageBackground}">
|
Background="{DynamicResource PageBackground}">
|
||||||
|
|
||||||
|
<!--Implementierung mit Unterstützung durch ChatGPT
|
||||||
|
Datum: 17.02.2026
|
||||||
|
Prompt sinngemäß: Как реализовать многоязычный Placeholder для DatePickerTextBox в WPF с использованием ресурсов (.resx) и привязки к текущей CultureInfo, чтобы текст обновлялся при смене языка приложения?-->
|
||||||
<Page.Resources>
|
<Page.Resources>
|
||||||
|
|
||||||
<!-- Стиль для внутреннего DatePickerTextBox -->
|
<!-- Style für Innertext DatePickerTextBox -->
|
||||||
<Style TargetType="DatePickerTextBox">
|
<Style TargetType="DatePickerTextBox">
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
@@ -16,7 +19,7 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<ScrollViewer x:Name="PART_ContentHost"/>
|
<ScrollViewer x:Name="PART_ContentHost"/>
|
||||||
|
|
||||||
<!-- Наш placeholder -->
|
<!-- placeholder -->
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Text="{x:Static properties:Resources.SelectDate}"
|
Text="{x:Static properties:Resources.SelectDate}"
|
||||||
Foreground="Gray"
|
Foreground="Gray"
|
||||||
|
|||||||
@@ -9,14 +9,12 @@ namespace SkyTeam
|
|||||||
{
|
{
|
||||||
public ReservierungssuchePage()
|
public ReservierungssuchePage()
|
||||||
{
|
{
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SearchFlights_Click(object sender, RoutedEventArgs e)
|
private void SearchFlights_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Simples Auslesen der Benutzereingaben aus den Textboxen und dem DatePicker
|
|
||||||
string from = FromBox.Text;
|
string from = FromBox.Text;
|
||||||
string to = ToBox.Text;
|
string to = ToBox.Text;
|
||||||
DateTime? date = DateBox.SelectedDate;
|
DateTime? date = DateBox.SelectedDate;
|
||||||
@@ -28,8 +26,6 @@ namespace SkyTeam
|
|||||||
NavigationService.Navigate(new verfuegbareFluge(from, to, date));
|
NavigationService.Navigate(new verfuegbareFluge(from, to, date));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quelle: Im Unterricht gemacht
|
|
||||||
// Lambda-Ausdrücke (=>) für kurze und übersichtliche Seitenwechsel über den NavigationService
|
|
||||||
private void HomeButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new NavigationPage());
|
private void HomeButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new NavigationPage());
|
||||||
private void BookingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new BuchungenPage());
|
private void BookingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new BuchungenPage());
|
||||||
private void SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
|
private void SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ namespace SkyTeam
|
|||||||
|
|
||||||
private void LoadFlights()
|
private void LoadFlights()
|
||||||
{
|
{
|
||||||
// Source: Stack Overflow "What is the purpose of using WHERE 1=1 in SQL statements?"
|
|
||||||
// Link: https://stackoverflow.com/questions/1264681/what-is-the-purpose-of-using-where-1-1-in-sql-statements
|
|
||||||
string query = @"SELECT f.Id, f.Flugnummer, f.Abflugort AS 'From', f.Zielort AS 'To',
|
string query = @"SELECT f.Id, f.Flugnummer, f.Abflugort AS 'From', f.Zielort AS 'To',
|
||||||
z.Modell AS Plane, f.Abflugdatum AS Date
|
z.Modell AS Plane, f.Abflugdatum AS Date
|
||||||
FROM fluege f
|
FROM fluege f
|
||||||
@@ -89,12 +87,9 @@ namespace SkyTeam
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Source: Stack Overflow "Get selected row item in DataGrid WPF"
|
// Source: Stack Overflow "Get selected row item in DataGrid WPF"
|
||||||
// Link: https://stackoverflow.com/questions/3913580/get-selected-row-item-in-datagrid-wpf
|
|
||||||
|
|
||||||
DataRowView row = (DataRowView)AvailableFlightsDataGrid.SelectedItem;
|
DataRowView row = (DataRowView)AvailableFlightsDataGrid.SelectedItem;
|
||||||
int flightId = Convert.ToInt32(row["Id"]);
|
int flightId = Convert.ToInt32(row["Id"]);
|
||||||
|
|
||||||
|
|
||||||
if (SessionManager.CurrentUserId == 0)
|
if (SessionManager.CurrentUserId == 0)
|
||||||
{
|
{
|
||||||
MessageBox.Show("Fehler: Nicht eingeloggt.");
|
MessageBox.Show("Fehler: Nicht eingeloggt.");
|
||||||
@@ -123,8 +118,6 @@ namespace SkyTeam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// quelle: Microsoft Learn "NavigationService.Navigate Method"
|
|
||||||
|
|
||||||
private void HomeButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new NavigationPage());
|
private void HomeButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new NavigationPage());
|
||||||
private void BookingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new BuchungenPage());
|
private void BookingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new BuchungenPage());
|
||||||
private void SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
|
private void SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
|
||||||
|
|||||||
BIN
Titel.docx
Normal file
BIN
Titel.docx
Normal file
Binary file not shown.
1
connectionstring.txt
Normal file
1
connectionstring.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Server=mysql.pb.bib.de;uid=pbt3h24akh;pwd=Dd3dwQgPeNxW;database=pbt3h24akh_SkyTeam;
|
||||||
Reference in New Issue
Block a user