Compare commits

...

24 Commits

Author SHA1 Message Date
4ac31f96df SkyTeam/SettingsPage.xaml.cs aktualisiert 2026-03-06 12:52:58 +01:00
666ed27772 SkyTeam/verfuegbareFluge.xaml.cs aktualisiert 2026-03-06 12:49:51 +01:00
72914f8fe7 SkyTeam/App.xaml.cs aktualisiert 2026-03-06 12:48:21 +01:00
50c7d92b45 SkyTeam/reservierungsSuche.xaml.cs aktualisiert 2026-03-06 12:46:57 +01:00
63db842f1c SkyTeam/AdminLoginPage.xaml.cs aktualisiert 2026-03-06 12:45:34 +01:00
037f81385c SkyTeam/Regestrieren.xaml.cs aktualisiert 2026-03-06 12:44:10 +01:00
10aec32770 SkyTeam/AdminDashBoard.xaml.cs aktualisiert 2026-03-06 12:42:04 +01:00
9af555bd25 SkyTeam/LogInPage.xaml.cs aktualisiert 2026-03-06 12:38:31 +01:00
dcae169c28 Dateien nach "/" hochladen
connectionstring.txt hinzugefügt
2026-03-06 10:10:40 +01:00
03c91f7dc9 PDF-Export für Flugbuchungen hinzugefügt 2026-03-06 10:01:43 +01:00
7603469aae Logo für App 2026-03-05 12:32:33 +01:00
9207d5e8d6 Tastaturnavigation auf der Login-Seite hinzugefügt 2026-02-25 10:35:23 +01:00
younes elhaddoury
95f71e34c7 connStr ist jzt nur geheim 2026-02-17 12:53:02 +01:00
e81a27834f Geheim Datebank Verbindung 2026-02-17 12:48:22 +01:00
94479d259c Übetsetzung aller Benutzerseiten hinzugefügt 2026-02-17 11:51:52 +01:00
e50f578547 Ukrainisch und Arabisch als Sprachen hinzugefügt 2026-02-13 12:19:18 +01:00
b4d70c4825 Mehrsprachigkeit mit Resx-Ressourcen und Sprachwechsel hinzugefügt 2026-02-13 11:44:52 +01:00
younes elhaddoury
57735cdf93 fix von viel errors in GUI und logik dahinter 2026-02-04 14:57:59 +01:00
younes elhaddoury
a76ddb3acd Probleme idenzifierung , müssen weiter gearbeitet 2026-02-03 13:53:24 +01:00
younes elhaddoury
241ed4eb94 last commit before tests 2026-02-03 13:31:40 +01:00
younes elhaddoury
3ba5b10d05 fix von minimalistischen Probleme und instalierung von BCrypt nugetpacket 2026-02-01 13:05:58 +01:00
younes elhaddoury
13621be669 alle fehler korigieren , alles ui ist funktionfähig , muss aber implementiert werden 2026-02-01 00:01:07 +01:00
younes elhaddoury
dbcc95d198 Resolve csproj conflict: keep ui-before-db version 2026-01-30 21:53:36 +01:00
younes elhaddoury
72cb729d7a fix problems 2026-01-30 10:14:40 +01:00
42 changed files with 4002 additions and 854 deletions

2
.gitignore vendored
View File

@@ -221,7 +221,7 @@ rcf/
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.txt
*.appx
*.appxbundle
*.appxupload

200
SkyTeam/AdminDashBoard.xaml Normal file
View File

@@ -0,0 +1,200 @@
<Page x:Class="SkyTeam.AdminDashboard"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:properties="clr-namespace:SkyTeam"
Title="AdminDashboard"
Background="{DynamicResource PageBackground}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0" Grid.ColumnSpan="2" Background="#D32F2F" Padding="15">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="ShieldAccount" Width="36" Height="36" Foreground="White" Margin="0,0,10,0"/>
<StackPanel>
<TextBlock Text="{x:Static properties:Resources.AdminHeaderTitle}" FontSize="20" FontWeight="Bold" Foreground="White"/>
<TextBlock Text="{x:Static properties:Resources.AdminHeaderSubtitle}" FontSize="12" Foreground="White"/>
</StackPanel>
</StackPanel>
</Border>
<StackPanel Grid.Row="1" Grid.Column="0" Background="{DynamicResource SidebarBackground}">
<Button Height="50" Margin="5" Click="ShowUsers_Click">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="AccountGroup" Width="20" Margin="0,0,10,0"/>
<TextBlock Text="{x:Static properties:Resources.AdminSidebarManageUsers}"/>
</StackPanel>
</Button>
<Button Height="50" Margin="5" Click="ShowFlights_Click">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Airplane" Width="20" Margin="0,0,10,0"/>
<TextBlock Text="{x:Static properties:Resources.AdminSidebarManageFlights}"/>
</StackPanel>
</Button>
<Button Height="50" Margin="5" Background="#FFEBEB" BorderBrush="#FFB71C1C" Foreground="#D32F2F" FontWeight="Bold" Click="Logout_Click">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Logout" Width="20" Margin="0,0,10,0"/>
<TextBlock Text="{x:Static properties:Resources.AdminSidebarLogout}"/>
</StackPanel>
</Button>
</StackPanel>
<Grid Grid.Row="1" Grid.Column="1" Margin="20">
<Grid x:Name="UserManagementGrid" Visibility="Visible">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="{x:Static properties:Resources.AdminUsersTitle}" FontSize="24" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
<DataGrid x:Name="AllUsersGrid" Grid.Row="1" Margin="0,10,0,20" AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Single" SelectionChanged="AllUsersGrid_SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Id}" Width="50"/>
<DataGridTextColumn Header="Vorname" Binding="{Binding Vorname}" Width="*"/>
<DataGridTextColumn Header="Nachname" Binding="{Binding Nachname}" Width="*"/>
<DataGridTextColumn Header="Email" Binding="{Binding Email}" Width="150"/>
<DataGridTextColumn Header="Rolle" Binding="{Binding Rolle}" Width="80"/>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0,0,0,10">
<TextBlock Text="{x:Static properties:Resources.AdminUserBookingsTitle}" FontSize="18" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}" VerticalAlignment="Center"/>
<Button Content="{x:Static properties:Resources.AdminDeleteUserButton}" Background="#D32F2F" Foreground="White" FontWeight="Bold" Margin="20,0,0,0" Padding="10,5" Click="DeleteUser_Click"/>
</StackPanel>
<DataGrid x:Name="UserBookingsGrid" Grid.Row="3" AutoGenerateColumns="False" IsReadOnly="True" Background="{DynamicResource CardBackground}">
<DataGrid.Columns>
<DataGridTextColumn Header="Buchung ID" Binding="{Binding BuchungId}"/>
<DataGridTextColumn Header="Flug Nr." Binding="{Binding Flugnummer}"/>
<DataGridTextColumn Header="Von" Binding="{Binding Abflugort}"/>
<DataGridTextColumn Header="Nach" Binding="{Binding Zielort}"/>
<DataGridTextColumn Header="Datum" Binding="{Binding Abflugdatum}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
<Grid x:Name="FlightManagementGrid" Visibility="Collapsed">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="{x:Static properties:Resources.AdminFlightsTitle}" FontSize="24" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}" Margin="0,0,0,10"/>
<DataGrid x:Name="AllFlightsGrid" Grid.Row="1" Margin="0,0,0,20" AutoGenerateColumns="False" IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Id}" Width="40"/>
<DataGridTextColumn Header="Nummer" Binding="{Binding Flugnummer}" FontWeight="Bold" Width="80"/>
<DataGridTextColumn Header="Von" Binding="{Binding Abflugort}" Width="*"/>
<DataGridTextColumn Header="Nach" Binding="{Binding Zielort}" Width="*"/>
<DataGridTextColumn Header="Datum" Binding="{Binding Abflugdatum}" Width="120"/>
<DataGridTextColumn Header="Preis" Binding="{Binding Preis}" Width="60"/>
<DataGridTextColumn Header="Flugzeug" Binding="{Binding Plane}" Width="100"/>
<DataGridTextColumn Header="Pilot" Binding="{Binding Pilot}" Width="100"/>
</DataGrid.Columns>
</DataGrid>
<Button Grid.Row="1" VerticalAlignment="Top" HorizontalAlignment="Right" Content="Flug Löschen" Background="#D32F2F" Foreground="White" Margin="0,-40,0,0" Padding="10,5" Click="DeleteFlight_Click"/>
<Border Grid.Row="2" Background="{DynamicResource CardBackground}" CornerRadius="8" Padding="15" BorderBrush="#DDD" BorderThickness="1">
<StackPanel>
<TextBlock Text="{x:Static properties:Resources.AdminAddFlightTitle}" FontWeight="Bold" Margin="0,0,0,10"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Margin="5">
<Label Content="{Binding Source={x:Static properties:Resources.PrepositionVon}, StringFormat='{}{0}:'}"/>
<ComboBox x:Name="AddFromCombo" IsEditable="True">
<ComboBoxItem Content="Berlin"/>
<ComboBoxItem Content="München"/>
<ComboBoxItem Content="Frankfurt"/>
<ComboBoxItem Content="Hamburg"/>
<ComboBoxItem Content="Paris"/>
<ComboBoxItem Content="London"/>
<ComboBoxItem Content="Madrid"/>
<ComboBoxItem Content="Rom"/>
<ComboBoxItem Content="Lissabon"/>
<ComboBoxItem Content="Wien"/>
<ComboBoxItem Content="Zürich"/>
<ComboBoxItem Content="Amsterdam"/>
<ComboBoxItem Content="Prag"/>
<ComboBoxItem Content="Budapest"/>
<ComboBoxItem Content="Warschau"/>
<ComboBoxItem Content="Paderborn"/>
</ComboBox>
</StackPanel>
<StackPanel Grid.Column="1" Margin="5">
<Label Content="{Binding Source={x:Static properties:Resources.To}, StringFormat='{}{0}:'}"/>
<ComboBox x:Name="AddToCombo" IsEditable="True">
<ComboBoxItem Content="Mallorca"/>
<ComboBoxItem Content="Berlin"/>
<ComboBoxItem Content="München"/>
<ComboBoxItem Content="Frankfurt"/>
<ComboBoxItem Content="Hamburg"/>
<ComboBoxItem Content="Paris"/>
<ComboBoxItem Content="London"/>
<ComboBoxItem Content="Madrid"/>
<ComboBoxItem Content="Rom"/>
<ComboBoxItem Content="Lissabon"/>
<ComboBoxItem Content="Wien"/>
<ComboBoxItem Content="Zürich"/>
<ComboBoxItem Content="Amsterdam"/>
<ComboBoxItem Content="Prag"/>
<ComboBoxItem Content="Budapest"/>
<ComboBoxItem Content="Tokio"/>
<ComboBoxItem Content="New York"/>
<ComboBoxItem Content="Dubai"/>
</ComboBox>
</StackPanel>
<StackPanel Grid.Column="2" Margin="5">
<Label Content="{Binding Source={x:Static properties:Resources.DateLabel}, StringFormat='{}{0}:'}"/>
<DatePicker x:Name="AddDatePick"/>
</StackPanel>
<StackPanel Grid.Column="3" Margin="5">
<Label Content="{Binding Source={x:Static properties:Resources.PriceLabel}, StringFormat='{}{0}:'}"/>
<TextBox x:Name="AddPriceTxt"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="0" Margin="5">
<Label Content="{Binding Source={x:Static properties:Resources.PlaneLabel}, StringFormat='{}{0}:'}"/>
<ComboBox x:Name="PlaneCombo" DisplayMemberPath="Modell" SelectedValuePath="Id"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" Margin="5">
<Label Content="{Binding Source={x:Static properties:Resources.PilotLabel}, StringFormat='{}{0}:'}"/>
<ComboBox x:Name="PilotCombo" DisplayMemberPath="FullName" SelectedValuePath="Id"/>
</StackPanel>
<Button Grid.Row="1" Grid.Column="3" Content="{x:Static properties:Resources.AdminCreateFlightButton}" Background="#1E88E5" Foreground="White" FontWeight="Bold" VerticalAlignment="Bottom" Height="30" Margin="5" Click="AddFlight_Click"/>
</Grid>
</StackPanel>
</Border>
</Grid>
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,170 @@
using System;
using System.Data;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using MySql.Data.MySqlClient;
namespace SkyTeam
{
public partial class AdminDashboard : Page
{
public AdminDashboard()
{
InitializeComponent();
LoadUsers();
LoadFlights();
LoadCombos();
}
private void LoadUsers()
{
BindGrid("SELECT Id, Vorname, Nachname, Email, Rolle FROM users", AllUsersGrid);
}
private void AllUsersGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (AllUsersGrid.SelectedItem == null) return;
DataRowView row = (DataRowView)AllUsersGrid.SelectedItem;
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);
}
private void DeleteUser_Click(object sender, RoutedEventArgs e)
{
if (AllUsersGrid.SelectedItem == null) { MessageBox.Show("Bitte User wählen"); return; }
DataRowView row = (DataRowView)AllUsersGrid.SelectedItem;
int uid = Convert.ToInt32(row["Id"]);
if (MessageBox.Show($"User {uid} löschen?", "Confirm", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
ExecuteSql($"DELETE FROM users WHERE Id={uid}");
LoadUsers();
UserBookingsGrid.ItemsSource = null;
}
}
private void LoadFlights()
{
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
FROM fluege f
JOIN flugzeuge z ON f.FlugzeugId = z.Id
JOIN piloten p ON f.PilotId = p.Id
ORDER BY f.Abflugdatum DESC";
BindGrid(q, AllFlightsGrid);
}
private void DeleteFlight_Click(object sender, RoutedEventArgs e)
{
if (AllFlightsGrid.SelectedItem == null) return;
DataRowView row = (DataRowView)AllFlightsGrid.SelectedItem;
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"]}");
LoadFlights();
}
}
private void AddFlight_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(AddFromCombo.Text) ||
string.IsNullOrWhiteSpace(AddToCombo.Text) ||
AddDatePick.SelectedDate == null ||
PlaneCombo.SelectedValue == null ||
PilotCombo.SelectedValue == null)
{
MessageBox.Show("Bitte alle Felder ausfüllen.");
return;
}
int creatorId = SessionManager.CurrentUserId;
if (creatorId == 0) creatorId = 1;
string flightNum = "SYJ-" + new Random().Next(100, 999);
string query = @"INSERT INTO fluege (Abflugort, Zielort, Abflugdatum, Ankunftsdatum, Flugnummer, Preis, FlugzeugId, PilotId, ErstelltVon)
VALUES (@from, @to, @date, @arr, @fnum, @price, @plane, @pilot, @admin)";
try
{
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
{
conn.Open();
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@from", AddFromCombo.Text);
cmd.Parameters.AddWithValue("@to", AddToCombo.Text);
cmd.Parameters.AddWithValue("@date", AddDatePick.SelectedDate.Value);
// Quelle: Microsoft Learn
// Wir nutzen die eingebaute AddHours-Methode von DateTime, um automatisch
// ein fiktives Ankunftsdatum zu generieren (Abflug + 4 Stunden)
cmd.Parameters.AddWithValue("@arr", AddDatePick.SelectedDate.Value.AddHours(4));
cmd.Parameters.AddWithValue("@fnum", flightNum);
cmd.Parameters.AddWithValue("@price", AddPriceTxt.Text);
cmd.Parameters.AddWithValue("@plane", PlaneCombo.SelectedValue);
cmd.Parameters.AddWithValue("@pilot", PilotCombo.SelectedValue);
cmd.Parameters.AddWithValue("@admin", creatorId);
cmd.ExecuteNonQuery();
MessageBox.Show($"Flug {flightNum} erstellt!");
LoadFlights();
}
}
catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); }
}
private void LoadCombos()
{
BindComboBox("SELECT Id, Modell FROM flugzeuge WHERE IstDefekt=0", PlaneCombo, "Modell", "Id");
BindComboBox("SELECT Id, CONCAT(Vorname, ' ', Nachname) AS FullName FROM piloten WHERE IstVerfuegbar=1", PilotCombo, "FullName", "Id");
}
// Quelle: AI Assistant (Gemini)
// Idee: DRY Prinzip (Don't Repeat Yourself) / Refactoring
// Die KI hat vorgeschlagen, die sehr repetitiven SQL-Verbindungs und Adapter Logiken
// in universelle Hilfsmethoden (BindGrid, BindComboBox, ExecuteSql) auszulagern.
// Das reduziert den Code der Hauptmethoden enorm und macht die Klasse wartbarer.
private void BindGrid(string q, DataGrid g)
{
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
// 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).
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 { }
}
private void ExecuteSql(string s)
{
try { using (var c = new MySqlConnection(DatenbankServices.GetConnection())) { c.Open(); new MySqlCommand(s, c).ExecuteNonQuery(); } } catch (Exception ex) { MessageBox.Show(ex.Message); }
}
private void ShowUsers_Click(object sender, RoutedEventArgs e)
{
UserManagementGrid.Visibility = Visibility.Visible;
FlightManagementGrid.Visibility = Visibility.Collapsed;
}
private void ShowFlights_Click(object sender, RoutedEventArgs e)
{
UserManagementGrid.Visibility = Visibility.Collapsed;
FlightManagementGrid.Visibility = Visibility.Visible;
LoadFlights();
}
private void Logout_Click(object sender, RoutedEventArgs e)
{
SessionManager.CurrentUserId = 0;
NavigationService.Navigate(new LogInPage());
}
}
}

View File

@@ -0,0 +1,39 @@
<Page x:Class="SkyTeam.AdminLoginPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
Title="Admin Login">
<Grid Margin="40,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,0,0,30">
<iconPacks:PackIconMaterial Kind="ShieldAccount" Width="40" Height="40" Foreground="#D32F2F" Margin="0,0,15,0"/>
<TextBlock Text="Admin Login" FontSize="36" FontWeight="Bold" Foreground="#D32F2F"/>
</StackPanel>
<Border Grid.Row="1" Background="White" CornerRadius="16" Padding="40" BorderBrush="#D32F2F" BorderThickness="2" VerticalAlignment="Center" HorizontalAlignment="Center">
<StackPanel Width="300">
<TextBlock Text="Sicherheits-Check" FontWeight="Bold" Margin="0,0,0,15" HorizontalAlignment="Center"/>
<Label Content="Vorname (Username):"/>
<TextBox x:Name="AdminUserBox" Height="35" Margin="0,0,0,10"/>
<Label Content="E-Mail:"/>
<TextBox x:Name="AdminEmailBox" Height="35" Margin="0,0,0,10"/>
<Label Content="Rolle (z.B. Admin):"/>
<TextBox x:Name="AdminRoleBox" Height="35" Margin="0,0,0,10"/>
<Label Content="Passwort:"/>
<PasswordBox x:Name="AdminPassBox" Height="35" Margin="0,0,0,20"/>
<Button Content="Admin Anmelden" Height="40" Background="#D32F2F" Foreground="White" FontWeight="Bold" Click="AdminLogin_Click"/>
<Button Content="Abbrechen" Margin="0,10,0,0" Background="Transparent" BorderThickness="0" Click="Back_Click"/>
</StackPanel>
</Border>
</Grid>
</Page>

View File

@@ -0,0 +1,77 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using MySql.Data.MySqlClient;
using BCrypt.Net;
namespace SkyTeam
{
public partial class AdminLoginPage : Page
{
// Quelle: Microsoft Learn
// Nutzung eines "Expression bodied members" (=>) für den Konstruktor
// Das macht Methoden oder Konstruktoren, die nur aus einer einzigen Zeile bestehen,
// deutlich kompakter und besser lesbar
public AdminLoginPage() => InitializeComponent();
private void AdminLogin_Click(object sender, RoutedEventArgs e)
{
string query = "SELECT Id, PasswortHash FROM users WHERE Email = @email AND Vorname = @user AND Rolle = @role";
try
{
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
{
conn.Open();
using (MySqlCommand cmd = new MySqlCommand(query, conn))
{
cmd.Parameters.AddWithValue("@email", AdminEmailBox.Text);
cmd.Parameters.AddWithValue("@user", AdminUserBox.Text);
cmd.Parameters.AddWithValue("@role", AdminRoleBox.Text);
using (MySqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
string storedHash = reader.GetString("PasswortHash");
int dbId = reader.GetInt32("Id");
// Quelle: Stack Overflow
// Genau wie beim normalen User-Login prüfen wir das Passwort lokal
// über die BCrypt-Bibliothek. Ein direkter Abgleich in der SQL-Datenbank
// (WHERE PasswortHash = @hash) ist unmöglich, da BCrypt dynamische Salts verwendet
if (BCrypt.Net.BCrypt.Verify(AdminPassBox.Password, storedHash))
{
// Quelle: AI Assistant (Gemini)
// Konsistentes State Management
// 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
SessionManager.CurrentUserId = dbId;
SessionManager.CurrentUserName = AdminUserBox.Text;
MessageBox.Show("Admin-Zugriff gewährt!");
NavigationService.Navigate(new AdminDashboard());
}
else
{
MessageBox.Show("Ungültiges Passwort.");
}
}
else
{
MessageBox.Show("Kein Admin mit diesen Daten gefunden.");
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show("Fehler: " + ex.Message);
}
}
private void Back_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new LogInPage());
}
}

View File

@@ -1,9 +1,12 @@
<Application x:Class="SkyTeam.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SkyTeam"
StartupUri="MainWindow.xaml">
<Application.Resources>
<SolidColorBrush x:Key="PageBackground" Color="White"/>
<SolidColorBrush x:Key="CardBackground" Color="#F5F7FA"/>
<SolidColorBrush x:Key="SidebarBackground" Color="#FFE3F2FD"/>
<SolidColorBrush x:Key="PrimaryText" Color="Black"/>
<SolidColorBrush x:Key="SecondaryText" Color="#666666"/>
</Application.Resources>
</Application>

View File

@@ -1,14 +1,65 @@
using System.Configuration;
using System.Data;
using BCrypt.Net;
using MySql.Data.MySqlClient;
using PdfSharp.Fonts;
using System.Globalization;
using System.Reflection;
using System.Windows;
using static SkyTeam.BuchungenPage;
namespace SkyTeam
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
// Beim Start der Anwendung einen Standard Admin-Benutzer erstellen, falls keiner existiert , selbGedacht.
public App()
{
// Quelle: Stack Overflow
// 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
// nutzt. Das verhindert Inkonsistenzen beim Laden der ersten Seite.
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de");
GlobalFontSettings.FontResolver = new CustomFontResolver();
}
private void CreateDefaultAdmin()
{
string connectionString = DatenbankServices.GetConnection();
try
{
using (MySqlConnection conn = new MySqlConnection(connectionString))
{
conn.Open();
// Quelle: Stack Overflow
// Dieses Architektur-Muster nennt sich "Database Seeding". Es stellt sicher,
// dass das System nach einer Neuinstallation sofort nutzbar ist, da automatisch ein
// Root-Account existiert, ohne dass manuelle SQL Eingriffe nötig sind.
string checkQuery = "SELECT COUNT(*) FROM users WHERE Rolle = 'Admin'";
MySqlCommand checkCmd = new MySqlCommand(checkQuery, conn);
long count = (long)checkCmd.ExecuteScalar();
if (count == 0)
{
string hashedPassword = BCrypt.Net.BCrypt.HashPassword("admin");
string insertQuery = @"
INSERT INTO users (Vorname, Nachname, Email, PasswortHash, Rolle, Stadt, CreatedAt)
VALUES ('System', 'Root', 'admin@skyteam.com', @hash, 'Admin', 'HQ', NOW())";
MySqlCommand insertCmd = new MySqlCommand(insertQuery, conn);
insertCmd.Parameters.AddWithValue("@hash", hashedPassword);
insertCmd.ExecuteNonQuery();
MessageBox.Show("Ein Standard-Admin wurde erstellt!\nEmail: admin@skyteam.com\nPasswort: admin");
}
}
}
catch(Exception ex) {
MessageBox.Show("Fehler beim Erstellen des Standard Admins: " + ex.Message);
}
}
}
}

View File

@@ -1,172 +1,96 @@
<Page x:Class="SkyTeam.MeineBuchungenPage"
<Page x:Class="SkyTeam.BuchungenPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
Title="MeineBuchungenPage">
xmlns:properties="clr-namespace:SkyTeam"
Title="BuchungenPage"
Background="{DynamicResource PageBackground}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0"
Grid.ColumnSpan="2"
Background="#FF1E88E5"
Padding="15">
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<Border Grid.Row="0" Grid.ColumnSpan="2" Background="#FF1E88E5" Padding="15">
<StackPanel Orientation="Horizontal">
<Ellipse Width="36" Height="36" Fill="White" Margin="0,0,10,0"/>
<StackPanel>
<TextBlock Text="Sky Team Airlines"
FontSize="20"
FontWeight="Bold"
Foreground="White"/>
<TextBlock Text="Sichere und komfortable Flüge weltweit"
FontSize="12"
Foreground="White"/>
<TextBlock Text="{x:Static properties:Resources.HeaderTitle}" FontSize="20" FontWeight="Bold" Foreground="White"/>
<TextBlock Text="{x:Static properties:Resources.HeaderSubtitle}" FontSize="12" Foreground="White"/>
</StackPanel>
</StackPanel>
</Border>
<StackPanel Grid.Row="1"
Grid.Column="0"
Background="#FFE3F2FD"
Orientation="Vertical">
<StackPanel Grid.Row="1" Grid.Column="0" Background="{DynamicResource SidebarBackground}">
<Button x:Name="HomeButton"
Height="50"
Margin="5"
Click="HomeButton_Click">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Home" Width="20" Height="20" Margin="0,0,10,0"/>
<TextBlock Text="Home"/>
<Button Height="50" Margin="5" Click="HomeButton_Click" Background="Transparent" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Home" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarHome}" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button x:Name="BookingsButton"
Height="50"
Margin="5"
Click="BookingsButton_Click"
Background="#FFBBDEFB">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Airplane" Width="20" Height="20" Margin="0,0,10,0"/>
<TextBlock Text="Meine Buchungen"/>
<Button Height="50" Margin="5" Click="BookingsButton_Click" Background="{DynamicResource CardBackground}" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Airplane" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarBookings}" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button x:Name="SettingsButton"
Height="50"
Margin="5"
Click="SettingsButton_Click">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Cog" Width="20" Height="20" Margin="0,0,10,0"/>
<TextBlock Text="Einstellungen"/>
<Button Height="50" Margin="5" Click="SettingsButton_Click" Background="Transparent" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Cog" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarSettings}" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button x:Name="LogoutButton"
Height="50"
Margin="5"
Background="#FFEBEB"
BorderBrush="#FFB71C1C"
Foreground="#D32F2F"
FontWeight="Bold"
Click="LogoutButton_Click">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Logout" Width="20" Height="20" Margin="0,0,10,0"/>
<TextBlock Text="Abmelden"/>
<Button Height="50" Margin="5" Background="#FFEBEB" BorderBrush="#FFB71C1C" Foreground="#D32F2F" FontWeight="Bold" Click="LogoutButton_Click">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Logout" Width="20" Margin="0,0,10,0"/>
<TextBlock Text="{x:Static properties:Resources.SidebarLogout}"/>
</StackPanel>
</Button>
</StackPanel>
<Grid Grid.Row="1" Grid.Column="1" Margin="30">
<StackPanel>
<TextBlock Text="{x:Static properties:Resources.SidebarBookings}" FontSize="28" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.FlightOverviewTitle}" FontSize="16" Foreground="{DynamicResource SecondaryText}" Margin="0,0,0,20"/>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border x:Name="NoBookingsView" Visibility="Visible" Background="{DynamicResource CardBackground}" CornerRadius="12" Padding="40">
<StackPanel HorizontalAlignment="Center">
<iconPacks:PackIconMaterial Kind="AirplaneOff" Width="50" Height="50" Foreground="#888"/>
<TextBlock Text="{x:Static properties:Resources.NoFlightReserved}" FontSize="18" Margin="0,15,0,5" TextAlignment="Center" Foreground="{DynamicResource PrimaryText}"/>
<Button Content="{x:Static properties:Resources.ReserveNow}" Width="180" Height="45" Background="#FF1E88E5" Foreground="White" FontWeight="Bold" Margin="0,20,0,0" Click="OpenReservierungSuche_Click"/>
</StackPanel>
</Border>
<StackPanel Grid.Row="0"
Orientation="Horizontal"
VerticalAlignment="Center"
Margin="0,0,0,20">
<iconPacks:PackIconMaterial Kind="Airplane" Width="28" Height="28" Margin="0,0,10,0"/>
<StackPanel>
<TextBlock Text="Meine Buchungen"
FontSize="24"
FontWeight="Bold"/>
<TextBlock Text="Übersicht über Ihre gebuchten Flüge"
FontSize="14"
Foreground="#666"/>
</StackPanel>
</StackPanel>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="0,0,0,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Von:" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,8,0"/>
<TextBox x:Name="FromFilterTextBox" Grid.Column="1" Height="36" Margin="0,0,12,0"/>
<Label Content="Nach:" Grid.Column="2" VerticalAlignment="Center" Margin="0,0,8,0"/>
<TextBox x:Name="ToFilterTextBox" Grid.Column="3" Height="36" Margin="0,0,12,0"/>
<Button x:Name="SearchBookingsButton"
Grid.Column="4"
Width="100"
Height="36"
Margin="0,0,0,0"
HorizontalAlignment="Right"
Click="SearchBookingsButton_Click">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Magnify" Width="18" Height="18" Margin="0,0,6,0"/>
<TextBlock Text="Suchen"/>
</StackPanel>
</Button>
</Grid>
<DataGrid x:Name="BookingsDataGrid"
Grid.Row="1"
<DataGrid x:Name="BookingsGrid"
Visibility="Collapsed"
AutoGenerateColumns="False"
IsReadOnly="True"
CanUserAddRows="False"
GridLinesVisibility="Horizontal"
HeadersVisibility="Column">
IsReadOnly="True"
Height="400"
Background="{DynamicResource CardBackground}"
SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Header="Buchungsnummer" Width="120" Binding="{Binding BookingNumber}"/>
<DataGridTextColumn Header="Von" Width="80" Binding="{Binding From}"/>
<DataGridTextColumn Header="Nach" Width="80" Binding="{Binding To}"/>
<DataGridTextColumn Header="Flugzeug" Width="100" Binding="{Binding Flugzeug}"/>
<DataGridTextColumn Header="Pilot" Width="100" Binding="{Binding Pilots}"/>
<DataGridTextColumn Header="Abflug" Width="140" Binding="{Binding DepartureTime}"/>
<DataGridTextColumn Header="Ankunft" Width="140" Binding="{Binding ArrivalTime}"/>
<DataGridTextColumn Header="Status" Width="100" Binding="{Binding Status}"/>
<DataGridTextColumn Header="{x:Static properties:Resources.BookingIdLabel}" Binding="{Binding BuchungId}" Width="100"/>
<DataGridTextColumn Header="{x:Static properties:Resources.FlightNumberShortLabel}" Binding="{Binding Flugnummer}" Width="*"/>
<DataGridTextColumn Header="{x:Static properties:Resources.PrepositionVon}" Binding="{Binding Abflugort}" Width="*"/>
<DataGridTextColumn Header="{x:Static properties:Resources.To}" Binding="{Binding Zielort}" Width="*"/>
<DataGridTextColumn Header="{x:Static properties:Resources.DateLabel}" Binding="{Binding Abflugdatum}" Width="*"/>
<DataGridTextColumn Header="{x:Static properties:Resources.StatusLabel}" Binding="{Binding Status}" Width="100"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
<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>
</Grid>
</Grid>
</Page>

View File

@@ -1,12 +1,19 @@
using System.Windows;
using MySql.Data.MySqlClient;
using PdfSharp.Drawing;
using PdfSharp.Fonts;
using PdfSharp.Pdf;
using System;
using System.Data;
using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.IO;
namespace SkyTeam
{
public partial class MeineBuchungenPage : Page
public partial class BuchungenPage : Page
{
public MeineBuchungenPage()
public BuchungenPage()
{
InitializeComponent();
LoadBookings();
@@ -14,56 +21,141 @@ namespace SkyTeam
private void LoadBookings()
{
if (SessionManager.CurrentUserId == 0) return;
var bookings = new ObservableCollection<object>
string query = @"SELECT b.Id AS BuchungId, f.Flugnummer, f.Abflugort, f.Zielort, f.Abflugdatum, b.Status
FROM buchungen b
JOIN fluege f ON b.FlugId = f.Id
WHERE b.UserId = @uid";
try
{
new { BookingNumber = "SKY001", From = "FRA", To = "JFK", DepartureTime = "2026-02-01 09:00", ArrivalTime = "2026-02-01 13:30", Status = "Bestätigt" },
new { BookingNumber = "SKY002", From = "MUC", To = "LAX", DepartureTime = "2026-02-03 14:20", ArrivalTime = "2026-02-04 08:45", Status = "Geplant" }
};
BookingsDataGrid.ItemsSource = bookings;
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
{
conn.Open();
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@uid", SessionManager.CurrentUserId);
MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
adapter.Fill(dt);
if (dt.Rows.Count > 0)
{
BookingsGrid.ItemsSource = dt.DefaultView;
NoBookingsView.Visibility = Visibility.Collapsed;
BookingsGrid.Visibility = Visibility.Visible;
CancelBtn.Visibility = Visibility.Visible;
CreatePdfBtn.Visibility = Visibility.Visible;
}
else
{
NoBookingsView.Visibility = Visibility.Visible;
BookingsGrid.Visibility = Visibility.Collapsed;
CancelBtn.Visibility = Visibility.Collapsed;
CreatePdfBtn.Visibility = Visibility.Collapsed;
}
}
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
}
private void SearchBookingsButton_Click(object sender, RoutedEventArgs e)
private void CancelBooking_Click(object sender, RoutedEventArgs e)
{
string from = FromFilterTextBox.Text;
string to = ToFilterTextBox.Text;
MessageBox.Show($"Suche Flüge von {from} nach {to}", "Suche", MessageBoxButton.OK);
}
private void HomeButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new NavigationPage());
}
private void BookingsButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new MeineBuchungenPage());
}
private void SettingsButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new SettingsPage());
}
private void BookFlightButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new MeineBuchungenPage());
}
private void LogoutButton_Click(object sender, RoutedEventArgs e)
{
var result = MessageBox.Show(
"Möchten Sie sich wirklich abmelden?",
"Abmelden",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
if (BookingsGrid.SelectedItem == null)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new LogInPage());
MessageBox.Show("Bitte wählen Sie einen Flug aus.");
return;
}
DataRowView row = (DataRowView)BookingsGrid.SelectedItem;
int bid = Convert.ToInt32(row["BuchungId"]);
if (MessageBox.Show("Stornieren?", "Confirm", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
{
conn.Open();
new MySqlCommand($"DELETE FROM buchungen WHERE Id={bid}", conn).ExecuteNonQuery();
}
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 BookingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new BuchungenPage());
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 OpenReservierungSuche_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new ReservierungssuchePage());
}
}

View File

@@ -3,17 +3,18 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using System.IO;
namespace SkyTeam
{
class DatenbankServices
static class DatenbankServices
{
private string ConnectionString = "Server=mysql.pb.bib.de;uid=pbt3h24akh;pwd=Dd3dwQgPeNxW;database=pbt3h24akh_SkyTeam;";
private static readonly string connectionString = File.ReadAllText("connectionstring.txt");
protected virtual string connectionString
public static string GetConnection()
{
get { return ConnectionString; }
private set { ConnectionString = value; }
return connectionString;
}

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SkyTeam
{
class FlugeRepo
{
}
}

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SkyTeam
{
class FlugzeugRepo
{
}
}

View File

@@ -2,150 +2,78 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
Title="NavigationPage">
xmlns:properties="clr-namespace:SkyTeam"
Title="NavigationPage"
Background="{DynamicResource PageBackground}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0"
Grid.ColumnSpan="2"
Background="#FF1E88E5"
Padding="15">
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<Ellipse Width="36"
Height="36"
Fill="White"
Margin="0,0,10,0"/>
<Border Grid.Row="0" Grid.ColumnSpan="2" Background="#FF1E88E5" Padding="15">
<StackPanel Orientation="Horizontal">
<Ellipse Width="36" Height="36" Fill="White" Margin="0,0,10,0"/>
<StackPanel>
<TextBlock Text="Sky Team Airlines"
FontSize="20"
FontWeight="Bold"
Foreground="White"/>
<TextBlock Text="Sichere und komfortable Flüge weltweit"
FontSize="12"
Foreground="White"/>
<TextBlock Text="{x:Static properties:Resources.HeaderTitle}" FontSize="20" FontWeight="Bold" Foreground="White"/>
<TextBlock Text="{x:Static properties:Resources.HeaderSubtitle}" FontSize="12" Foreground="White"/>
</StackPanel>
</StackPanel>
</Border>
<StackPanel Grid.Row="1"
Grid.Column="0"
Background="#FFE3F2FD"
Orientation="Vertical">
<StackPanel Grid.Row="1" Grid.Column="0" Background="{DynamicResource SidebarBackground}">
<Button x:Name="HomeButton"
Height="50"
Margin="5"
Click="HomeButton_Click"
Background="#FFBBDEFB">
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Home"
Width="20"
Height="20"
Margin="0,0,10,0"/>
<TextBlock Text="Home"/>
<Button x:Name="HomeButton" Height="50" Margin="5" Click="HomeButton_Click" Background="{DynamicResource CardBackground}" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Home" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarHome}" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button x:Name="BookingsButton"
Height="50"
Margin="5"
Click="BookingsButton_Click">
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Airplane"
Width="20"
Height="20"
Margin="0,0,10,0"/>
<TextBlock Text="Meine Buchungen"/>
<Button x:Name="BookingsButton" Height="50" Margin="5" Click="BookingsButton_Click" Background="Transparent" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Airplane" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarBookings}" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button x:Name="SettingsButton"
Height="50"
Margin="5"
Click="SettingsButton_Click">
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Cog"
Width="20"
Height="20"
Margin="0,0,10,0"/>
<TextBlock Text="Einstellungen"/>
<Button x:Name="SettingsButton" Height="50" Margin="5" Click="SettingsButton_Click" Background="Transparent" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Cog" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarSettings}" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button x:Name="LogoutButton"
Height="50"
Margin="5"
Background="#FFEBEB"
BorderBrush="#FFB71C1C"
Foreground="#D32F2F"
FontWeight="Bold"
Click="LogoutButton_Click">
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Logout"
Width="20"
Height="20"
Margin="0,0,10,0"/>
<TextBlock Text="Abmelden"/>
<Button x:Name="LogoutButton" Height="50" Margin="5" Background="#FFEBEB" BorderBrush="#FFB71C1C" Foreground="#D32F2F" FontWeight="Bold" Click="LogoutButton_Click">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Logout" Width="20" Margin="0,0,10,0"/>
<TextBlock Text="{x:Static properties:Resources.SidebarLogout}"/>
</StackPanel>
</Button>
</StackPanel>
<ScrollViewer Grid.Row="1"
Grid.Column="1"
Margin="30"
VerticalScrollBarVisibility="Auto">
<ScrollViewer Grid.Row="1" Grid.Column="1" Margin="30" VerticalScrollBarVisibility="Auto">
<StackPanel Margin="0,0,0,30">
<StackPanel Orientation="Horizontal"
Margin="0,0,0,30">
<iconPacks:PackIconMaterial Kind="AirplaneTakeoff"
Width="48"
Height="48"
Margin="0,0,15,0"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,30">
<iconPacks:PackIconMaterial Kind="AirplaneTakeoff" Width="48" Height="48" Foreground="{DynamicResource PrimaryText}" Margin="0,0,15,0"/>
<StackPanel>
<TextBlock Text="Willkommen bei Sky Team Airlines"
FontSize="28"
FontWeight="Bold"/>
<TextBlock Text="Exklusive Flugservices für Privatzylinder"
FontSize="16"
Foreground="Gray"/>
<TextBlock Text="{x:Static properties:Resources.WelcomeTitle}" FontSize="28" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.WelcomeSubtitle}" FontSize="16" Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
</StackPanel>
<Border Background="#F8F9FA"
Padding="25"
CornerRadius="8"
Margin="0,0,0,25">
<TextBlock Text="Sky Team Airlines bietet konfortable Veranstaltung von Privatjets für Geschäftsreisende. Unsere moderne Flotte mit den neuesten Businessjets garantiert Ihnen maximale Komfort auf Ihren Flügen."
FontSize="14"
LineHeight="22"
TextWrapping="Wrap"/>
<Border Background="{DynamicResource CardBackground}" Padding="25" CornerRadius="8" Margin="0,0,0,25">
<TextBlock Text="{x:Static properties:Resources.WelcomeDescription}"
FontSize="14" LineHeight="22" TextWrapping="Wrap" Foreground="{DynamicResource PrimaryText}"/>
</Border>
<TextBlock Text="Unsere Services"
FontSize="20"
FontWeight="Bold"
Margin="0,0,15,0"/>
<TextBlock Text="{x:Static properties:Resources.ServicesTitle}" FontSize="20" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}" Margin="0,0,15,0"/>
<Grid>
<Grid.ColumnDefinitions>
@@ -153,70 +81,33 @@
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0"
Margin="0,0,15,0"
Padding="20"
Background="#E3F2FD"
CornerRadius="8">
<Border Grid.Column="0" Margin="0,0,15,0" Padding="20" Background="{DynamicResource CardBackground}" CornerRadius="8">
<StackPanel>
<iconPacks:PackIconMaterial Kind="AccountGroup"
Width="32"
Height="32"
Foreground="#1E88E5"/>
<TextBlock Text="Persönliche Kundenbetreuung"
FontSize="16"
FontWeight="Bold"
Margin="0,10,0,5"/>
<TextBlock Text="Dedizierte Flugplanung und individuelle Bedürfnisse"
FontSize="13"
Foreground="Gray"
TextWrapping="Wrap"/>
<iconPacks:PackIconMaterial Kind="AccountGroup" Width="32" Height="32" Foreground="#1E88E5"/>
<TextBlock Text="{x:Static properties:Resources.ServicePersonalSupport}" FontSize="16" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}" Margin="0,10,0,5"/>
<TextBlock Text="{x:Static properties:Resources.ServicePersonalSupportDesc}" FontSize="13" Foreground="{DynamicResource SecondaryText}" TextWrapping="Wrap"/>
</StackPanel>
</Border>
<Border Grid.Column="1"
Padding="20"
Background="#E8F5E8"
CornerRadius="8">
<Border Grid.Column="1" Padding="20" Background="{DynamicResource CardBackground}" CornerRadius="8">
<StackPanel>
<iconPacks:PackIconMaterial Kind="Database"
Width="32"
Height="32"
Foreground="#388E3C"/>
<TextBlock Text="Sichere Datenverwaltung"
FontSize="16"
FontWeight="Bold"
Margin="0,10,0,5"/>
<TextBlock Text="Vollständiger CRUD für Kunden, Flüge, Piloten"
FontSize="13"
Foreground="Gray"
TextWrapping="Wrap"/>
<iconPacks:PackIconMaterial Kind="Database" Width="32" Height="32" Foreground="#388E3C"/>
<TextBlock Text="{x:Static properties:Resources.ServiceDataSecurity}" FontSize="16" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}" Margin="0,10,0,5"/>
<TextBlock Text="{x:Static properties:Resources.ServiceDataSecurityDesc}" FontSize="13" Foreground="{DynamicResource SecondaryText}" TextWrapping="Wrap"/>
</StackPanel>
</Border>
</Grid>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
Margin="0,40,0,0">
<Button Width="200"
Height="50"
Background="#FF1E88E5"
Foreground="White"
FontSize="16"
FontWeight="Bold"
Click="BookFlightButton_Click">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,40,0,0">
<Button Width="200" Height="50" Background="#FF1E88E5" Foreground="White" FontSize="16" FontWeight="Bold" Click="BookFlightButton_Click">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Airplane"
Width="24"
Height="24"
Margin="0,0,12,0"/>
<TextBlock Text="Jetzt Flug buchen"/>
<iconPacks:PackIconMaterial Kind="Airplane" Width="24" Height="24" Margin="0,0,12,0"/>
<TextBlock Text="{x:Static properties:Resources.BookFlightButton}"/>
</StackPanel>
</Button>
</StackPanel>
</StackPanel>
</ScrollViewer>
</Grid>
</Page>

View File

@@ -8,7 +8,6 @@ namespace SkyTeam
public NavigationPage()
{
InitializeComponent();
}
private void HomeButton_Click(object sender, RoutedEventArgs e)
@@ -18,7 +17,7 @@ namespace SkyTeam
private void BookingsButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new MeineBuchungenPage());
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new BuchungenPage());
}
private void SettingsButton_Click(object sender, RoutedEventArgs e)
@@ -28,7 +27,7 @@ namespace SkyTeam
private void BookFlightButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new MeineBuchungenPage());
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new BuchungenPage());
}
private void LogoutButton_Click(object sender, RoutedEventArgs e)
{

View File

@@ -2,46 +2,26 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
Title="LogInPage">
Title="LogInPage"
KeyboardNavigation.DirectionalNavigation="Cycle"
Loaded="Page_Loaded">
<Grid Margin="40,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="0,0,0,50">
<iconPacks:PackIconMaterial Kind="Account"
Width="36"
Height="36"
Margin="0,0,15,0"/>
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,0,0,50">
<iconPacks:PackIconMaterial Kind="Account" Width="36" Height="36" Margin="0,0,15,0"/>
<StackPanel>
<TextBlock Text="Sky Team"
FontSize="36"
FontWeight="Bold"/>
<TextBlock Text="Melden Sie sich an um zu starten"
FontSize="14"
Foreground="#666"
Margin="0,5,0,0"/>
<TextBlock Text="Sky Team" FontSize="36" FontWeight="Bold"/>
<TextBlock Text="Melden Sie sich an um zu starten" FontSize="14" Foreground="#666" Margin="0,5,0,0"/>
</StackPanel>
</StackPanel>
<!-- Form Container -->
<Border Grid.Row="1"
Background="White"
CornerRadius="16"
Padding="50"
BorderBrush="#E0E0E0"
BorderThickness="1"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Border Grid.Row="1" Background="White" CornerRadius="16" Padding="50" BorderBrush="#E0E0E0" BorderThickness="1" VerticalAlignment="Center" HorizontalAlignment="Center">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
@@ -50,65 +30,25 @@
<RowDefinition Height="Auto"/>
<RowDefinition Height="40"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Email (Benutzername):" Grid.Row="0" FontWeight="SemiBold"/>
<TextBox x:Name="BenutzernameTextBox" Grid.Row="1" Height="45" FontSize="14" VerticalContentAlignment="Center" TabIndex="0" PreviewKeyDown="BenutzernameTextBox_PreviewKeyDown"/>
<Label Content="Benutzername:"
Grid.Row="0" Grid.Column="0"
VerticalAlignment="Center"
Margin="0,0,12,8"
FontSize="14"
FontWeight="SemiBold"/>
<TextBox x:Name="BenutzernameTextBox"
Grid.Row="1" Grid.ColumnSpan="2"
Height="45"
FontSize="14"
Margin="0,0,0,0"/>
<Label Content="Passwort:" Grid.Row="3" FontWeight="SemiBold"/>
<PasswordBox x:Name="PasswortTextBox" Grid.Row="4" Height="45" FontSize="14" VerticalContentAlignment="Center" TabIndex="1"/>
<Label Content="Passwort:"
Grid.Row="3" Grid.Column="0"
VerticalAlignment="Center"
Margin="0,0,12,8"
FontSize="14"
FontWeight="SemiBold"/>
<PasswordBox x:Name="PasswortTextBox"
Grid.Row="4" Grid.ColumnSpan="2"
Height="45"
FontSize="14"
Margin="0,0,0,0"/>
<StackPanel Grid.Row="6"
Grid.ColumnSpan="2"
Orientation="Horizontal"
HorizontalAlignment="Center"
Margin="0,20,0,0">
<Button Content="Login"
Width="140"
Height="48"
Margin="0,0,20,0"
Background="#FF1E88E5"
Foreground="White"
FontSize="15"
FontWeight="Bold"
Click="LogInButton_Click"/>
<Button Content="Registrieren"
Width="140"
Height="48"
Background="Transparent"
BorderBrush="#DDD"
BorderThickness="1"
Foreground="#666"
FontSize="15"
FontWeight="SemiBold"
Click="anmeldungsButton_Click"/>
<StackPanel Grid.Row="6" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,20,0,0">
<Button Content="Login" Width="140" Height="48" Margin="0,0,20,0" Background="#FF1E88E5" Foreground="White" FontWeight="Bold" Click="LogInButton_Click" TabIndex="2" IsDefault="True"/>
<Button Content="Registrieren" Width="140" Height="48" Background="Transparent" BorderBrush="#DDD" Foreground="#666" Click="anmeldungsButton_Click" TabIndex="3"/>
</StackPanel>
<TextBlock Grid.Row="7" HorizontalAlignment="Center" Margin="0,20,0,0">
<Run Text="Sind Sie Admin?" Foreground="#666"/>
<Hyperlink Click="AdminLink_Click" Foreground="#1E88E5" TextDecorations="None" FontWeight="Bold">Bitte hier klicken</Hyperlink>
</TextBlock>
</Grid>
</Border>
</Grid>
</Page>

View File

@@ -1,46 +1,123 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BCrypt.Net;
using MySql.Data.MySqlClient;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SkyTeam
{
/// <summary>
/// Interaction logic for LogInPage.xaml
/// </summary>
public partial class LogInPage : Page
{
public LogInPage()
{
InitializeComponent();
}
// Quelle: Im Unterricht gemacht
private void AdminLink_Click(object sender, RoutedEventArgs e)
{
if (Application.Current.MainWindow is MainWindow mainWindow)
{
mainWindow.MainFrame.Navigate(new AdminLoginPage());
}
}
private void LogInButton_Click(object sender, RoutedEventArgs e)
{
string email = BenutzernameTextBox.Text;
string password = PasswortTextBox.Password;
// Quelle: Im Unterricht gemacht
// Basis Validierung auf leere Felder
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password))
{
MessageBox.Show("Bitte Email und Passwort eingeben.");
return;
}
string query = @"
SELECT Id, Vorname, Rolle, PasswortHash
FROM users
WHERE Email = @email";
try
{
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
{
conn.Open();
using (MySqlCommand cmd = new MySqlCommand(query, conn))
{
cmd.Parameters.AddWithValue("@email", email);
using (MySqlDataReader reader = cmd.ExecuteReader())
{
if (!reader.Read())
{
MessageBox.Show("Benutzer wurde nicht gefunden.");
return;
}
// Quelle: Stack Overflow "How to verify a BCrypt hash"
// 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.
// Wir müssen erst den gespeicherten Hash aus der DB laden und dann die Verify Methode
// der BCrypt-Bibliothek nutzen, um das Klartext passwort damit zu prüfen
string storedHash = reader.GetString("PasswortHash");
if (!BCrypt.Net.BCrypt.Verify(password, storedHash))
{
MessageBox.Show("Falsches Passwort.");
return;
}
// Quelle: AI Assistant (chat gpt)
// Idee: Globales State-Management über eine statische Klasse (SessionManager)
// 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.
// So sind User-ID, Name und Rolle global für die gesamte Laufzeit abrufbar.
SessionManager.CurrentUserId = reader.GetInt32("Id");
SessionManager.CurrentUserName = reader.GetString("Vorname");
SessionManager.Role = reader.GetString("Rolle");
}
}
((MainWindow)Application.Current.MainWindow)
.MainFrame.Navigate(new NavigationPage());
}
}
catch (Exception ex)
{
MessageBox.Show("Datenbankfehler: " + ex.Message);
}
}
private void anmeldungsButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new RegistrationPage());
((MainWindow)Application.Current.MainWindow)
.MainFrame.Navigate(new RegistrationPage());
}
private void LogInButton_Click(object sender, RoutedEventArgs e)
private void Page_Loaded(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new NavigationPage());
// Quelle: Im Unterricht gemacht
// Setzt den Cursor direkt beim Laden der Seite ins Benutzernamen-Feld.
BenutzernameTextBox.Focus();
}
private void BenutzernameTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
// Quelle: Stack Overflow "WPF Move focus on enter key"
// 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
// (das Passwort Feld), ohne dass der User die Maus benutzen muss
if (e.Key == Key.Down || e.Key == Key.Enter)
{
TraversalRequest request =
new TraversalRequest(FocusNavigationDirection.Next);
(sender as UIElement).MoveFocus(request);
e.Handled = true;
}
}
}
}

View File

@@ -4,7 +4,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SkyTeam"
mc:Ignorable="d"
xmlns:properties="clr-namespace:SkyTeam"
Title="Sky Team Airlines"
Height="700"
Width="1100"

View File

@@ -8,32 +8,16 @@ namespace SkyTeam
public MainWindow()
{
InitializeComponent();
<<<<<<< HEAD
TestDatabaseConnection();
}
private void TestDatabaseConnection()
{
DataBase db = new DataBase();
bool success = db.TestConnection();
if (success)
MessageBox.Show("Datenbank ist verfügbar!", "Erfolg", MessageBoxButton.OK, MessageBoxImage.Information);
else
MessageBox.Show("Probleme mit der Verbindung.", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
=======
ShowLoginPage();
}
private void ShowLoginPage()
{
MainFrame.Navigate(new LogInPage());
}
public void NavigateToApp()
{
MainFrame.Navigate(new NavigationPage());
>>>>>>> deaa68880afaf3dd53903180eef7a43c3e23056a
}
}
}

Binary file not shown.

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SkyTeam
{
class PilotenRepo
{
}
}

View File

@@ -2,10 +2,10 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
Title="Registrierungsseite">
Title="Registrierungsseite"
Background="#F0F2F5">
<Grid Margin="40,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
@@ -14,32 +14,34 @@
<StackPanel Grid.Row="0"
Orientation="Horizontal"
VerticalAlignment="Center"
Margin="0,0,0,40">
Margin="0,0,0,30">
<iconPacks:PackIconMaterial Kind="AccountPlus"
Width="32"
Height="32"
Width="40"
Height="40"
Foreground="#1E88E5"
Margin="0,0,15,0"/>
<StackPanel>
<TextBlock Text="Registrieren"
FontSize="28"
FontWeight="Bold"/>
FontWeight="Bold"
Foreground="#333"/>
<TextBlock Text="Erstellen Sie Ihren Sky Team Account"
FontSize="14"
Foreground="#666"/>
</StackPanel>
</StackPanel>
<Border Grid.Row="1"
Background="White"
CornerRadius="12"
Padding="40"
Padding="30"
BorderBrush="#E0E0E0"
BorderThickness="1"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Grid>
VerticalAlignment="Top"
HorizontalAlignment="Center"
MaxWidth="500">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
@@ -48,62 +50,62 @@
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="60"/>
<RowDefinition Height="40"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="220"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Label Content="Vorname:"
Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,8"/>
<TextBox x:Name="FirstNameTextBox" Grid.Row="0" Grid.Column="1" Margin="0,0,0,8"/>
<Label Content="Anrede:" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,12"/>
<ComboBox x:Name="SalutationComboBox" Grid.Row="0" Grid.Column="1" Margin="0,0,0,12" Height="30" VerticalContentAlignment="Center">
<ComboBoxItem Content="Herr"/>
<ComboBoxItem Content="Frau"/>
<ComboBoxItem Content="Divers"/>
</ComboBox>
<Label Content="Nachname:" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,8"/>
<TextBox x:Name="LastNameTextBox" Grid.Row="1" Grid.Column="1" Margin="0,0,0,8"/>
<Label Content="Vorname:" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,12"/>
<TextBox x:Name="FirstNameTextBox" Grid.Row="1" Grid.Column="1" Margin="0,0,0,12" Height="30" VerticalContentAlignment="Center"/>
<Label Content="E-Mail:" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,8"/>
<TextBox x:Name="EmailTextBox" Grid.Row="2" Grid.Column="1" Margin="0,0,0,8"/>
<Label Content="Nachname:" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,12"/>
<TextBox x:Name="LastNameTextBox" Grid.Row="2" Grid.Column="1" Margin="0,0,0,12" Height="30" VerticalContentAlignment="Center"/>
<Label Content="Telefonnummer:" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,8"/>
<TextBox x:Name="PhoneNumberTextBox" Grid.Row="3" Grid.Column="1" Margin="0,0,0,8"/>
<Label Content="Geburtsdatum:" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,12"/>
<DatePicker x:Name="BirthDatePicker" Grid.Row="3" Grid.Column="1" Margin="0,0,0,12" Height="30" VerticalContentAlignment="Center"/>
<Label Content="Stadt:" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,8"/>
<TextBox x:Name="CityTextBox" Grid.Row="4" Grid.Column="1" Margin="0,0,0,8"/>
<Label Content="E-Mail:" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,12"/>
<TextBox x:Name="EmailTextBox" Grid.Row="4" Grid.Column="1" Margin="0,0,0,12" Height="30" VerticalContentAlignment="Center"/>
<Label Content="Land:" Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,8"/>
<TextBox x:Name="CountryTextBox" Grid.Row="5" Grid.Column="1" Margin="0,0,0,8"/>
<Label Content="Stadt:" Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,12"/>
<TextBox x:Name="CityTextBox" Grid.Row="5" Grid.Column="1" Margin="0,0,0,12" Height="30" VerticalContentAlignment="Center"/>
<Label Content="Passwort:" Grid.Row="6" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,0"/>
<PasswordBox x:Name="PasswordBox" Grid.Row="6" VerticalAlignment="Top" Margin="1,4,0,0" Height="21" Grid.Column="1"/>
<Label Content="Land:" Grid.Row="6" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,12"/>
<TextBox x:Name="CountryTextBox" Grid.Row="6" Grid.Column="1" Margin="0,0,0,12" Height="30" VerticalContentAlignment="Center"/>
<StackPanel Grid.Row="9"
Grid.ColumnSpan="2"
Orientation="Horizontal"
HorizontalAlignment="Center">
<Label Content="Passwort:" Grid.Row="7" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,12,0"/>
<PasswordBox x:Name="PasswordBox" Grid.Row="7" Grid.Column="1" Height="30" VerticalContentAlignment="Center"/>
<StackPanel Grid.Row="9" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="Registrieren"
Width="130"
Height="42"
Margin="0,0,20,0"
Background="#FF1E88E5"
Width="120"
Height="40"
Margin="0,0,15,0"
Background="#1E88E5"
Foreground="White"
FontWeight="Bold"
FontSize="14"
Click="RegisterButton_Click"/>
<Button Content="Abbrechen"
Width="130"
Height="42"
Width="120"
Height="40"
Background="#F5F5F5"
BorderBrush="#DDD"
Click="CancelButton_Click"/>
</StackPanel>
</Grid>
</Border>
</Grid>
</Page>

View File

@@ -1,23 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using MySql.Data.MySqlClient;
using BCrypt.Net;
namespace SkyTeam
{
/// <summary>
/// Interaction logic for Page1.xaml
/// </summary>
public partial class RegistrationPage : Page
{
public RegistrationPage()
@@ -25,20 +14,113 @@ namespace SkyTeam
InitializeComponent();
}
private void RegisterButton_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(EmailTextBox.Text) || string.IsNullOrWhiteSpace(PasswordBox.Password))
{
MessageBox.Show("Bitte geben Sie Email und Passwort ein.");
return;
}
if (!IsValidEmail(EmailTextBox.Text))
{
MessageBox.Show("Bitte geben Sie eine gültige E-Mail-Adresse ein (z.B. name@domain.com).");
return;
}
string emailToCheck = EmailTextBox.Text;
try
{
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
{
conn.Open();
string checkQuery = "SELECT COUNT(*) FROM users WHERE Email = @email";
using (MySqlCommand checkCmd = new MySqlCommand(checkQuery, conn))
{
checkCmd.Parameters.AddWithValue("@email", emailToCheck);
long userCount = (long)checkCmd.ExecuteScalar();
if (userCount > 0)
{
MessageBox.Show("Sie haben bereits ein Konto mit dieser E-Mail. Bitte löschen Sie es, bevor Sie ein neues erstellen.",
"Konto existiert bereits", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
}
string hashedPassword = BCrypt.Net.BCrypt.HashPassword(PasswordBox.Password);
string insertQuery = "INSERT INTO users (Vorname, Nachname, Email, PasswortHash, Rolle, Stadt, Anrede, Geburtsdatum) " +
"VALUES (@vorname, @nachname, @email, @password, 'User', @stadt, @anrede, @geburtsdatum)";
using (MySqlCommand cmd = new MySqlCommand(insertQuery, conn))
{
string selectedAnrede = (SalutationComboBox.SelectedItem as ComboBoxItem)?.Content.ToString();
DateTime? selectedDate = BirthDatePicker.SelectedDate;
cmd.Parameters.AddWithValue("@vorname", FirstNameTextBox.Text);
cmd.Parameters.AddWithValue("@nachname", LastNameTextBox.Text);
cmd.Parameters.AddWithValue("@email", emailToCheck);
cmd.Parameters.AddWithValue("@password", hashedPassword);
cmd.Parameters.AddWithValue("@stadt", CityTextBox.Text);
// Quelle: Microsoft Learn - "DBNull.Value Field"
// Link: https://learn.microsoft.com/en-us/dotnet/api/system.dbnull.value
// Wenn optionale Felder (wie Anrede oder Geburtsdatum) leer bleiben,
// 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
cmd.Parameters.AddWithValue("@anrede", selectedAnrede ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@geburtsdatum", selectedDate.HasValue ? selectedDate.Value : (object)DBNull.Value);
cmd.ExecuteNonQuery();
}
}
MessageBox.Show("Dein Konto wurde erfolgreich angelegt!");
// Quelle: AI Assistant (Gemini)
// Idee: Navigation aus einer Page heraus, die in einem Frame gehostet wird.
// Kommentar: Die KI hat darauf hingewiesen, dass eine Page (wie die RegistrationPage)
// 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.
if (Application.Current.MainWindow is MainWindow mainWindow)
{
mainWindow.MainFrame.Navigate(new LogInPage());
}
}
catch (Exception ex)
{
MessageBox.Show("Etwas ist schief gelaufen: " + ex.Message);
}
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new LogInPage());
if (Application.Current.MainWindow is MainWindow mainWindow)
{
mainWindow.MainFrame.Navigate(new LogInPage());
}
}
private bool IsValidEmail(string email)
{
if (string.IsNullOrWhiteSpace(email))
return false;
try
{
// 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
// Kommentar: Wir nutzen den offiziell empfohlenen Regex-Ausdruck von Microsoft,
// kombiniert mit einem Timeout (250ms), um Denial-of-Service-Angriffe durch
// extrem lange oder fehlerhafte Strings (ReDoS) zu verhindern.
return Regex.IsMatch(email,
@"^[^@\s]+@[^@\s]+\.[^@\s]+$",
RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
}
catch (RegexMatchTimeoutException)
{
return false;
}
}
}
}

576
SkyTeam/Resources.Designer.cs generated Normal file
View File

@@ -0,0 +1,576 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SkyTeam {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SkyTeam.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Neuen Flug hinzufügen (ID wird generiert: SYJ-XXX) ähnelt.
/// </summary>
public static string AdminAddFlightTitle {
get {
return ResourceManager.GetString("AdminAddFlightTitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Flug Erstellen ähnelt.
/// </summary>
public static string AdminCreateFlightButton {
get {
return ResourceManager.GetString("AdminCreateFlightButton", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Flug Löschen ähnelt.
/// </summary>
public static string AdminDeleteFlightButton {
get {
return ResourceManager.GetString("AdminDeleteFlightButton", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Benutzer Löschen ähnelt.
/// </summary>
public static string AdminDeleteUserButton {
get {
return ResourceManager.GetString("AdminDeleteUserButton", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Flugplan &amp; Management ähnelt.
/// </summary>
public static string AdminFlightsTitle {
get {
return ResourceManager.GetString("AdminFlightsTitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Management Console ähnelt.
/// </summary>
public static string AdminHeaderSubtitle {
get {
return ResourceManager.GetString("AdminHeaderSubtitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Sky Team ADMIN ähnelt.
/// </summary>
public static string AdminHeaderTitle {
get {
return ResourceManager.GetString("AdminHeaderTitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Abmelden ähnelt.
/// </summary>
public static string AdminSidebarLogout {
get {
return ResourceManager.GetString("AdminSidebarLogout", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Flüge verwalten ähnelt.
/// </summary>
public static string AdminSidebarManageFlights {
get {
return ResourceManager.GetString("AdminSidebarManageFlights", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Benutzer verwalten ähnelt.
/// </summary>
public static string AdminSidebarManageUsers {
get {
return ResourceManager.GetString("AdminSidebarManageUsers", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Buchungen des ausgewählten Benutzers ähnelt.
/// </summary>
public static string AdminUserBookingsTitle {
get {
return ResourceManager.GetString("AdminUserBookingsTitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Alle Benutzer ähnelt.
/// </summary>
public static string AdminUsersTitle {
get {
return ResourceManager.GetString("AdminUsersTitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Verfügbare Flüge ähnelt.
/// </summary>
public static string AvailableFlightsTitle {
get {
return ResourceManager.GetString("AvailableFlightsTitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Buchen ähnelt.
/// </summary>
public static string BookButtonLabel {
get {
return ResourceManager.GetString("BookButtonLabel", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Jetzt Flug buchen ähnelt.
/// </summary>
public static string BookFlightButton {
get {
return ResourceManager.GetString("BookFlightButton", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Buchungs-ID ähnelt.
/// </summary>
public static string BookingIdLabel {
get {
return ResourceManager.GetString("BookingIdLabel", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Flug stornieren ähnelt.
/// </summary>
public static string CancelFlightButton {
get {
return ResourceManager.GetString("CancelFlightButton", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Wählen Sie Ihre bevorzugte Sprache ähnelt.
/// </summary>
public static string ChooseLanguage {
get {
return ResourceManager.GetString("ChooseLanguage", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Als PDF exportieren ähnelt.
/// </summary>
public static string CreatePdfButton {
get {
return ResourceManager.GetString("CreatePdfButton", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Passen Sie Ihr Erlebnis an ähnelt.
/// </summary>
public static string CustomizeExperience {
get {
return ResourceManager.GetString("CustomizeExperience", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Gefahrenzone ähnelt.
/// </summary>
public static string DangerZone {
get {
return ResourceManager.GetString("DangerZone", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Dark Mode ähnelt.
/// </summary>
public static string DarkMode {
get {
return ResourceManager.GetString("DarkMode", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Datum ähnelt.
/// </summary>
public static string DateLabel {
get {
return ResourceManager.GetString("DateLabel", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Konto löschen ähnelt.
/// </summary>
public static string DeleteAccount {
get {
return ResourceManager.GetString("DeleteAccount", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Das Löschen Ihres Kontos ist endgültig und kann nicht rückgängig gemacht werden. ähnelt.
/// </summary>
public static string DeleteAccountWarning {
get {
return ResourceManager.GetString("DeleteAccountWarning", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Abflugdaten ähnelt.
/// </summary>
public static string DepartureDate {
get {
return ResourceManager.GetString("DepartureDate", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Dunkles Design aktivieren ähnelt.
/// </summary>
public static string EnableDarkMode {
get {
return ResourceManager.GetString("EnableDarkMode", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Flug Nummer ähnelt.
/// </summary>
public static string FlightNumberLabel {
get {
return ResourceManager.GetString("FlightNumberLabel", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Flug-Nr. ähnelt.
/// </summary>
public static string FlightNumberShortLabel {
get {
return ResourceManager.GetString("FlightNumberShortLabel", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Ihre reservierten Flüge im Überblick ähnelt.
/// </summary>
public static string FlightOverviewTitle {
get {
return ResourceManager.GetString("FlightOverviewTitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Sichere und komfortable Flüge weltweit ähnelt.
/// </summary>
public static string HeaderSubtitle {
get {
return ResourceManager.GetString("HeaderSubtitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Sky Team Airlines ähnelt.
/// </summary>
public static string HeaderTitle {
get {
return ResourceManager.GetString("HeaderTitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Sprache ähnelt.
/// </summary>
public static string Language {
get {
return ResourceManager.GetString("Language", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Sie haben noch keinen Flug reserviert. ähnelt.
/// </summary>
public static string NoFlightReserved {
get {
return ResourceManager.GetString("NoFlightReserved", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Pilot ähnelt.
/// </summary>
public static string PilotLabel {
get {
return ResourceManager.GetString("PilotLabel", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Flugzeug ähnelt.
/// </summary>
public static string PlaneLabel {
get {
return ResourceManager.GetString("PlaneLabel", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Von ähnelt.
/// </summary>
public static string PrepositionVon {
get {
return ResourceManager.GetString("PrepositionVon", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Preis (€) ähnelt.
/// </summary>
public static string PriceLabel {
get {
return ResourceManager.GetString("PriceLabel", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Jetzt reservieren ähnelt.
/// </summary>
public static string ReserveNow {
get {
return ResourceManager.GetString("ReserveNow", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Flüge suchen ähnelt.
/// </summary>
public static string SearchFlights {
get {
return ResourceManager.GetString("SearchFlights", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Datum auswählen ähnelt.
/// </summary>
public static string SelectDate {
get {
return ResourceManager.GetString("SelectDate", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Wählen Sie einen Flug aus und klicken Sie auf Buchen ähnelt.
/// </summary>
public static string SelectFlightInstruction {
get {
return ResourceManager.GetString("SelectFlightInstruction", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Sichere Datenverwaltung ähnelt.
/// </summary>
public static string ServiceDataSecurity {
get {
return ResourceManager.GetString("ServiceDataSecurity", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Vollständiger CRUD für Kunden, Flüge, Piloten ähnelt.
/// </summary>
public static string ServiceDataSecurityDesc {
get {
return ResourceManager.GetString("ServiceDataSecurityDesc", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Persönliche Kundenbetreuung ähnelt.
/// </summary>
public static string ServicePersonalSupport {
get {
return ResourceManager.GetString("ServicePersonalSupport", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Individuelle Flugplanung und maßgeschneiderte Lösungen ähnelt.
/// </summary>
public static string ServicePersonalSupportDesc {
get {
return ResourceManager.GetString("ServicePersonalSupportDesc", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Unsere Services ähnelt.
/// </summary>
public static string ServicesTitle {
get {
return ResourceManager.GetString("ServicesTitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Meine Buchungen ähnelt.
/// </summary>
public static string SidebarBookings {
get {
return ResourceManager.GetString("SidebarBookings", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Startseite ähnelt.
/// </summary>
public static string SidebarHome {
get {
return ResourceManager.GetString("SidebarHome", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Abmelden ähnelt.
/// </summary>
public static string SidebarLogout {
get {
return ResourceManager.GetString("SidebarLogout", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Einstellungen ähnelt.
/// </summary>
public static string SidebarSettings {
get {
return ResourceManager.GetString("SidebarSettings", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Status ähnelt.
/// </summary>
public static string StatusLabel {
get {
return ResourceManager.GetString("StatusLabel", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Nach ähnelt.
/// </summary>
public static string To {
get {
return ResourceManager.GetString("To", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Bis ähnelt.
/// </summary>
public static string ToLabel {
get {
return ResourceManager.GetString("ToLabel", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Sky Team Airlines bietet komfortable Veranstaltung von Privatjets für Geschäftsreisende. Unsere moderne Flotte mit den neuesten Businessjets garantiert Ihnen maximalen Komfort auf Ihren Flügen. ähnelt.
/// </summary>
public static string WelcomeDescription {
get {
return ResourceManager.GetString("WelcomeDescription", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Exklusive Flugservices für Privatjets ähnelt.
/// </summary>
public static string WelcomeSubtitle {
get {
return ResourceManager.GetString("WelcomeSubtitle", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Willkommen bei Sky Team Airlines ähnelt.
/// </summary>
public static string WelcomeTitle {
get {
return ResourceManager.GetString("WelcomeTitle", resourceCulture);
}
}
}
}

291
SkyTeam/Resources.ar.resx Normal file
View File

@@ -0,0 +1,291 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AdminAddFlightTitle" xml:space="preserve">
<value> إضافة رحلة جديدة</value>
</data>
<data name="AdminCreateFlightButton" xml:space="preserve">
<value>إنشاء رحلة</value>
</data>
<data name="DateLabel" xml:space="preserve">
<value>التاريخ</value>
</data>
<data name="AdminDeleteFlightButton" xml:space="preserve">
<value>حذف الرحلة</value>
</data>
<data name="AdminDeleteUserButton" xml:space="preserve">
<value>حذف المستخدم</value>
</data>
<data name="AdminFlightsTitle" xml:space="preserve">
<value>جدول الرحلات وإدارة</value>
</data>
<data name="PrepositionVon" xml:space="preserve">
<value>من</value>
</data>
<data name="AdminHeaderSubtitle" xml:space="preserve">
<value>وحدة إدارة</value>
</data>
<data name="AdminHeaderTitle" xml:space="preserve">
<value>سكاي تيم الإدارة</value>
</data>
<data name="PilotLabel" xml:space="preserve">
<value>الطيار</value>
</data>
<data name="PriceLabel" xml:space="preserve">
<value>السعر (€)</value>
</data>
<data name="AdminSidebarLogout" xml:space="preserve">
<value>تسجيل الخروج</value>
</data>
<data name="AdminSidebarManageFlights" xml:space="preserve">
<value>إدارة الرحلات</value>
</data>
<data name="AdminSidebarManageUsers" xml:space="preserve">
<value>إدارة المستخدمين</value>
</data>
<data name="AdminUserBookingsTitle" xml:space="preserve">
<value>حجوزات المستخدم المحدد</value>
</data>
<data name="AdminUsersTitle" xml:space="preserve">
<value>جميع المستخدمين</value>
</data>
<data name="BookFlightButton" xml:space="preserve">
<value>احجز الرحلة الآن</value>
</data>
<data name="ChooseLanguage" xml:space="preserve">
<value>اختر لغتك المفضلة</value>
</data>
<data name="CustomizeExperience" xml:space="preserve">
<value>خصص تجربتك</value>
</data>
<data name="DangerZone" xml:space="preserve">
<value>منطقة الخطر</value>
</data>
<data name="DarkMode" xml:space="preserve">
<value>الوضع الداكن</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>حذف الحساب</value>
</data>
<data name="DeleteAccountWarning" xml:space="preserve">
<value>حذف حسابك نهائي ولا يمكن التراجع عنه.</value>
</data>
<data name="DepartureDate" xml:space="preserve">
<value>تاريخ الرحلة</value>
</data>
<data name="EnableDarkMode" xml:space="preserve">
<value>تفعيل الوضع الداكن</value>
</data>
<data name="FlightOverviewTitle" xml:space="preserve">
<value>نظرة عامة على الرحلات المحجوزة الخاصة بك</value>
</data>
<data name="HeaderSubtitle" xml:space="preserve">
<value>رحلات آمنة ومريحة حول العالم</value>
</data>
<data name="HeaderTitle" xml:space="preserve">
<value>سكاي تيم للطيران</value>
</data>
<data name="Language" xml:space="preserve">
<value>اللغة</value>
</data>
<data name="NoFlightReserved" xml:space="preserve">
<value>لم تقم بحجز أي رحلة بعد.</value>
</data>
<data name="ReserveNow" xml:space="preserve">
<value>احجز الآن</value>
</data>
<data name="SearchFlights" xml:space="preserve">
<value>ابحث عن الرحلات</value>
</data>
<data name="SelectDate" xml:space="preserve">
<value>اختر التاريخ</value>
</data>
<data name="ServiceDataSecurity" xml:space="preserve">
<value>إدارة بيانات آمنة</value>
</data>
<data name="ServiceDataSecurityDesc" xml:space="preserve">
<value>CRUD كامل للعملاء والرحلات والطيارين</value>
</data>
<data name="ServicePersonalSupport" xml:space="preserve">
<value>دعم عملاء شخصي</value>
</data>
<data name="ServicePersonalSupportDesc" xml:space="preserve">
<value>تخطيط رحلات مخصص واحتياجات فردية</value>
</data>
<data name="ServicesTitle" xml:space="preserve">
<value>خدماتنا</value>
</data>
<data name="SidebarBookings" xml:space="preserve">
<value>حجوزاتي</value>
</data>
<data name="SidebarHome" xml:space="preserve">
<value>الرئيسية</value>
</data>
<data name="SidebarLogout" xml:space="preserve">
<value>تسجيل الخروج</value>
</data>
<data name="SidebarSettings" xml:space="preserve">
<value>الإعدادات</value>
</data>
<data name="To" xml:space="preserve">
<value>إلى</value>
</data>
<data name="WelcomeDescription" xml:space="preserve">
<value>تقدم سكاي تيم للطيران خدمات طائرات خاصة مريحة للمسافرين من رجال الأعمال. تضمن أسطولنا الحديث من أحدث الطائرات الخاصة أقصى درجات الراحة في رحلاتك.</value>
</data>
<data name="WelcomeSubtitle" xml:space="preserve">
<value>خدمات طيران حصرية للطائرات الخاصة</value>
</data>
<data name="WelcomeTitle" xml:space="preserve">
<value>مرحبًا بكم في سكاي تيم للطيران</value>
</data>
<data name="FlightNumberLabel" xml:space="preserve">
<value>رقم الرحلة</value>
</data>
<data name="ToLabel" xml:space="preserve">
<value>إلى</value>
</data>
<data name="PlaneLabel" xml:space="preserve">
<value>الطائرة</value>
</data>
<data name="BookButtonLabel" xml:space="preserve">
<value>حجز</value>
</data>
<data name="AvailableFlightsTitle" xml:space="preserve">
<value>الرحلات المتاحة</value>
</data>
<data name="SelectFlightInstruction" xml:space="preserve">
<value>اختر رحلة ثم اضغط على حجز</value>
</data>
<data name="BookingIdLabel" xml:space="preserve">
<value>رقم الحجز</value>
</data>
<data name="FlightNumberShortLabel" xml:space="preserve">
<value>رقم الرحلة</value>
</data>
<data name="StatusLabel" xml:space="preserve">
<value>الحالة</value>
</data>
<data name="CancelFlightButton" xml:space="preserve">
<value>إلغاء الرحلة</value>
</data>
<data name="CreatePdfButton" xml:space="preserve">
<value>تصدير إلى PDF</value>
</data>
</root>

291
SkyTeam/Resources.en.resx Normal file
View File

@@ -0,0 +1,291 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AdminAddFlightTitle" xml:space="preserve">
<value>Add new flight (ID generated: SYJ-XXX)</value>
</data>
<data name="AdminCreateFlightButton" xml:space="preserve">
<value>Create flight</value>
</data>
<data name="DateLabel" xml:space="preserve">
<value>Date</value>
</data>
<data name="AdminDeleteFlightButton" xml:space="preserve">
<value>Delete flight</value>
</data>
<data name="AdminDeleteUserButton" xml:space="preserve">
<value>Delete user</value>
</data>
<data name="AdminFlightsTitle" xml:space="preserve">
<value>Flight schedule &amp; management</value>
</data>
<data name="PrepositionVon" xml:space="preserve">
<value>From</value>
</data>
<data name="AdminHeaderSubtitle" xml:space="preserve">
<value>Management Console</value>
</data>
<data name="AdminHeaderTitle" xml:space="preserve">
<value>Sky Team ADMIN</value>
</data>
<data name="PilotLabel" xml:space="preserve">
<value>Pilot</value>
</data>
<data name="PriceLabel" xml:space="preserve">
<value>Price (€)</value>
</data>
<data name="AdminSidebarLogout" xml:space="preserve">
<value>Logout</value>
</data>
<data name="AdminSidebarManageFlights" xml:space="preserve">
<value>Manage flights</value>
</data>
<data name="AdminSidebarManageUsers" xml:space="preserve">
<value>Manage users</value>
</data>
<data name="AdminUserBookingsTitle" xml:space="preserve">
<value>Selected user bookings</value>
</data>
<data name="AdminUsersTitle" xml:space="preserve">
<value>All users</value>
</data>
<data name="BookFlightButton" xml:space="preserve">
<value>Book Flight Now</value>
</data>
<data name="ChooseLanguage" xml:space="preserve">
<value>Choose your preferred language</value>
</data>
<data name="CustomizeExperience" xml:space="preserve">
<value>Customize your experience</value>
</data>
<data name="DangerZone" xml:space="preserve">
<value>Danger Zone</value>
</data>
<data name="DarkMode" xml:space="preserve">
<value>Dark Mode</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>
<data name="DeleteAccountWarning" xml:space="preserve">
<value>Deleting your account is permanent and cannot be undone.</value>
</data>
<data name="DepartureDate" xml:space="preserve">
<value>Departure Date</value>
</data>
<data name="EnableDarkMode" xml:space="preserve">
<value>Enable dark theme</value>
</data>
<data name="FlightOverviewTitle" xml:space="preserve">
<value>Your reserved flights overview</value>
</data>
<data name="HeaderSubtitle" xml:space="preserve">
<value>Safe and comfortable flights worldwide</value>
</data>
<data name="HeaderTitle" xml:space="preserve">
<value>Sky Team Airlines</value>
</data>
<data name="Language" xml:space="preserve">
<value>Language</value>
</data>
<data name="NoFlightReserved" xml:space="preserve">
<value>You have not reserved any flight yet.</value>
</data>
<data name="ReserveNow" xml:space="preserve">
<value>Reserve now</value>
</data>
<data name="SearchFlights" xml:space="preserve">
<value>Search Flights</value>
</data>
<data name="SelectDate" xml:space="preserve">
<value>Select Date</value>
</data>
<data name="ServiceDataSecurity" xml:space="preserve">
<value>Secure Data Management</value>
</data>
<data name="ServiceDataSecurityDesc" xml:space="preserve">
<value>Full management of customers, flights and pilots</value>
</data>
<data name="ServicePersonalSupport" xml:space="preserve">
<value>Personal Customer Support</value>
</data>
<data name="ServicePersonalSupportDesc" xml:space="preserve">
<value>Individual flight planning and tailored solutions</value>
</data>
<data name="ServicesTitle" xml:space="preserve">
<value>Our Services</value>
</data>
<data name="SidebarBookings" xml:space="preserve">
<value>My Bookings</value>
</data>
<data name="SidebarHome" xml:space="preserve">
<value>Home</value>
</data>
<data name="SidebarLogout" xml:space="preserve">
<value>Logout</value>
</data>
<data name="SidebarSettings" xml:space="preserve">
<value>Settings</value>
</data>
<data name="To" xml:space="preserve">
<value>To</value>
</data>
<data name="WelcomeDescription" xml:space="preserve">
<value>Sky Team Airlines offers comfortable private jet services for business travelers. Our modern fleet with the latest business jets guarantees maximum comfort on your flights.</value>
</data>
<data name="WelcomeSubtitle" xml:space="preserve">
<value>Exclusive private jet flight services</value>
</data>
<data name="WelcomeTitle" xml:space="preserve">
<value>Welcome to Sky Team Airlines</value>
</data>
<data name="FlightNumberLabel" xml:space="preserve">
<value>Flight Number</value>
</data>
<data name="ToLabel" xml:space="preserve">
<value>To</value>
</data>
<data name="PlaneLabel" xml:space="preserve">
<value>Plane</value>
</data>
<data name="BookButtonLabel" xml:space="preserve">
<value>Book</value>
</data>
<data name="AvailableFlightsTitle" xml:space="preserve">
<value>Available Flights</value>
</data>
<data name="SelectFlightInstruction" xml:space="preserve">
<value>Select a flight and click on Book</value>
</data>
<data name="BookingIdLabel" xml:space="preserve">
<value>Booking ID</value>
</data>
<data name="FlightNumberShortLabel" xml:space="preserve">
<value>Flight No.</value>
</data>
<data name="StatusLabel" xml:space="preserve">
<value>Status</value>
</data>
<data name="CancelFlightButton" xml:space="preserve">
<value>Cancel Flight</value>
</data>
<data name="CreatePdfButton" xml:space="preserve">
<value>Export as PDF</value>
</data>
</root>

291
SkyTeam/Resources.resx Normal file
View File

@@ -0,0 +1,291 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AdminAddFlightTitle" xml:space="preserve">
<value>Neuen Flug hinzufügen (ID wird generiert: SYJ-XXX)</value>
</data>
<data name="AdminCreateFlightButton" xml:space="preserve">
<value>Flug Erstellen</value>
</data>
<data name="DateLabel" xml:space="preserve">
<value>Datum</value>
</data>
<data name="AdminDeleteFlightButton" xml:space="preserve">
<value>Flug Löschen</value>
</data>
<data name="AdminDeleteUserButton" xml:space="preserve">
<value>Benutzer Löschen</value>
</data>
<data name="AdminFlightsTitle" xml:space="preserve">
<value>Flugplan &amp; Management</value>
</data>
<data name="PrepositionVon" xml:space="preserve">
<value>Von</value>
</data>
<data name="AdminHeaderSubtitle" xml:space="preserve">
<value>Management Console</value>
</data>
<data name="AdminHeaderTitle" xml:space="preserve">
<value>Sky Team ADMIN</value>
</data>
<data name="PilotLabel" xml:space="preserve">
<value>Pilot</value>
</data>
<data name="PriceLabel" xml:space="preserve">
<value>Preis (€)</value>
</data>
<data name="AdminSidebarLogout" xml:space="preserve">
<value>Abmelden</value>
</data>
<data name="AdminSidebarManageFlights" xml:space="preserve">
<value>Flüge verwalten</value>
</data>
<data name="AdminSidebarManageUsers" xml:space="preserve">
<value>Benutzer verwalten</value>
</data>
<data name="AdminUserBookingsTitle" xml:space="preserve">
<value>Buchungen des ausgewählten Benutzers</value>
</data>
<data name="AdminUsersTitle" xml:space="preserve">
<value>Alle Benutzer</value>
</data>
<data name="BookFlightButton" xml:space="preserve">
<value>Jetzt Flug buchen</value>
</data>
<data name="ChooseLanguage" xml:space="preserve">
<value>Wählen Sie Ihre bevorzugte Sprache</value>
</data>
<data name="CustomizeExperience" xml:space="preserve">
<value>Passen Sie Ihr Erlebnis an</value>
</data>
<data name="DangerZone" xml:space="preserve">
<value>Gefahrenzone</value>
</data>
<data name="DarkMode" xml:space="preserve">
<value>Dark Mode</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Konto löschen</value>
</data>
<data name="DeleteAccountWarning" xml:space="preserve">
<value>Das Löschen Ihres Kontos ist endgültig und kann nicht rückgängig gemacht werden.</value>
</data>
<data name="DepartureDate" xml:space="preserve">
<value>Abflugdaten</value>
</data>
<data name="EnableDarkMode" xml:space="preserve">
<value>Dunkles Design aktivieren</value>
</data>
<data name="FlightOverviewTitle" xml:space="preserve">
<value>Ihre reservierten Flüge im Überblick</value>
</data>
<data name="HeaderSubtitle" xml:space="preserve">
<value>Sichere und komfortable Flüge weltweit</value>
</data>
<data name="HeaderTitle" xml:space="preserve">
<value>Sky Team Airlines</value>
</data>
<data name="Language" xml:space="preserve">
<value>Sprache</value>
</data>
<data name="NoFlightReserved" xml:space="preserve">
<value>Sie haben noch keinen Flug reserviert.</value>
</data>
<data name="ReserveNow" xml:space="preserve">
<value>Jetzt reservieren</value>
</data>
<data name="SearchFlights" xml:space="preserve">
<value>Flüge suchen</value>
</data>
<data name="SelectDate" xml:space="preserve">
<value>Datum auswählen</value>
</data>
<data name="ServiceDataSecurity" xml:space="preserve">
<value>Sichere Datenverwaltung</value>
</data>
<data name="ServiceDataSecurityDesc" xml:space="preserve">
<value>Vollständiger CRUD für Kunden, Flüge, Piloten</value>
</data>
<data name="ServicePersonalSupport" xml:space="preserve">
<value>Persönliche Kundenbetreuung</value>
</data>
<data name="ServicePersonalSupportDesc" xml:space="preserve">
<value>Individuelle Flugplanung und maßgeschneiderte Lösungen</value>
</data>
<data name="ServicesTitle" xml:space="preserve">
<value>Unsere Services</value>
</data>
<data name="SidebarBookings" xml:space="preserve">
<value>Meine Buchungen</value>
</data>
<data name="SidebarHome" xml:space="preserve">
<value>Startseite</value>
</data>
<data name="SidebarLogout" xml:space="preserve">
<value>Abmelden</value>
</data>
<data name="SidebarSettings" xml:space="preserve">
<value>Einstellungen</value>
</data>
<data name="To" xml:space="preserve">
<value>Nach</value>
</data>
<data name="WelcomeDescription" xml:space="preserve">
<value>Sky Team Airlines bietet komfortable Veranstaltung von Privatjets für Geschäftsreisende. Unsere moderne Flotte mit den neuesten Businessjets garantiert Ihnen maximalen Komfort auf Ihren Flügen.</value>
</data>
<data name="WelcomeSubtitle" xml:space="preserve">
<value>Exklusive Flugservices für Privatjets</value>
</data>
<data name="WelcomeTitle" xml:space="preserve">
<value>Willkommen bei Sky Team Airlines</value>
</data>
<data name="FlightNumberLabel" xml:space="preserve">
<value>Flug Nummer</value>
</data>
<data name="ToLabel" xml:space="preserve">
<value>Bis</value>
</data>
<data name="PlaneLabel" xml:space="preserve">
<value>Flugzeug</value>
</data>
<data name="BookButtonLabel" xml:space="preserve">
<value>Buchen</value>
</data>
<data name="AvailableFlightsTitle" xml:space="preserve">
<value>Verfügbare Flüge</value>
</data>
<data name="SelectFlightInstruction" xml:space="preserve">
<value>Wählen Sie einen Flug aus und klicken Sie auf Buchen</value>
</data>
<data name="BookingIdLabel" xml:space="preserve">
<value>Buchungs-ID</value>
</data>
<data name="FlightNumberShortLabel" xml:space="preserve">
<value>Flug-Nr.</value>
</data>
<data name="StatusLabel" xml:space="preserve">
<value>Status</value>
</data>
<data name="CancelFlightButton" xml:space="preserve">
<value>Flug stornieren</value>
</data>
<data name="CreatePdfButton" xml:space="preserve">
<value>Als PDF exportieren</value>
</data>
</root>

291
SkyTeam/Resources.uk.resx Normal file
View File

@@ -0,0 +1,291 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AdminAddFlightTitle" xml:space="preserve">
<value>Додати новий рейс (ID генерується: SYJ-XXX)</value>
</data>
<data name="AdminCreateFlightButton" xml:space="preserve">
<value>Створити рейс</value>
</data>
<data name="DateLabel" xml:space="preserve">
<value>Дата</value>
</data>
<data name="AdminDeleteFlightButton" xml:space="preserve">
<value>Видалити рейс</value>
</data>
<data name="AdminDeleteUserButton" xml:space="preserve">
<value>Видалити користувача</value>
</data>
<data name="AdminFlightsTitle" xml:space="preserve">
<value>Розклад рейсів та управління</value>
</data>
<data name="PrepositionVon" xml:space="preserve">
<value>Звідки</value>
</data>
<data name="AdminHeaderSubtitle" xml:space="preserve">
<value>Консоль управління</value>
</data>
<data name="AdminHeaderTitle" xml:space="preserve">
<value>Sky Team ADMIN</value>
</data>
<data name="PilotLabel" xml:space="preserve">
<value>Пілот</value>
</data>
<data name="PriceLabel" xml:space="preserve">
<value>Ціна (€)</value>
</data>
<data name="AdminSidebarLogout" xml:space="preserve">
<value>Вийти</value>
</data>
<data name="AdminSidebarManageFlights" xml:space="preserve">
<value>Керування рейсами</value>
</data>
<data name="AdminSidebarManageUsers" xml:space="preserve">
<value>Керування користувачами</value>
</data>
<data name="AdminUserBookingsTitle" xml:space="preserve">
<value>Бронювання обраного користувача</value>
</data>
<data name="AdminUsersTitle" xml:space="preserve">
<value>Усі користувачі</value>
</data>
<data name="BookFlightButton" xml:space="preserve">
<value>Забронювати рейс</value>
</data>
<data name="ChooseLanguage" xml:space="preserve">
<value>Виберіть бажану мову</value>
</data>
<data name="CustomizeExperience" xml:space="preserve">
<value>Налаштуйте свій досвід</value>
</data>
<data name="DangerZone" xml:space="preserve">
<value>Зона ризику</value>
</data>
<data name="DarkMode" xml:space="preserve">
<value>Темний режим</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Видалити акаунт</value>
</data>
<data name="DeleteAccountWarning" xml:space="preserve">
<value>Видалення вашого акаунту є остаточним і не можна скасувати.</value>
</data>
<data name="DepartureDate" xml:space="preserve">
<value>Дата вильоту</value>
</data>
<data name="EnableDarkMode" xml:space="preserve">
<value>Увімкнути темну тему</value>
</data>
<data name="FlightOverviewTitle" xml:space="preserve">
<value>Ваші заброньовані рейси</value>
</data>
<data name="HeaderSubtitle" xml:space="preserve">
<value>Безпечні та комфортні перельоти по всьому світу</value>
</data>
<data name="HeaderTitle" xml:space="preserve">
<value>Sky Team Airlines (UA)</value>
</data>
<data name="Language" xml:space="preserve">
<value>Мова</value>
</data>
<data name="NoFlightReserved" xml:space="preserve">
<value>Ви ще не забронювали жодного рейсу.</value>
</data>
<data name="ReserveNow" xml:space="preserve">
<value>Забронювати зараз</value>
</data>
<data name="SearchFlights" xml:space="preserve">
<value>Пошук рейсів</value>
</data>
<data name="SelectDate" xml:space="preserve">
<value>Виберіть дату</value>
</data>
<data name="ServiceDataSecurity" xml:space="preserve">
<value>Безпечне управління даними</value>
</data>
<data name="ServiceDataSecurityDesc" xml:space="preserve">
<value>Повний CRUD для клієнтів, рейсів, пілотів</value>
</data>
<data name="ServicePersonalSupport" xml:space="preserve">
<value>Персональне обслуговування клієнтів</value>
</data>
<data name="ServicePersonalSupportDesc" xml:space="preserve">
<value>Індивідуальне планування рейсу та особисті потреби</value>
</data>
<data name="ServicesTitle" xml:space="preserve">
<value>Наші послуги</value>
</data>
<data name="SidebarBookings" xml:space="preserve">
<value>Мої бронювання</value>
</data>
<data name="SidebarHome" xml:space="preserve">
<value>Головна</value>
</data>
<data name="SidebarLogout" xml:space="preserve">
<value>Вийти</value>
</data>
<data name="SidebarSettings" xml:space="preserve">
<value>Налаштування</value>
</data>
<data name="To" xml:space="preserve">
<value>Куди</value>
</data>
<data name="WelcomeDescription" xml:space="preserve">
<value>Sky Team Airlines пропонує комфортні послуги приватних джетів для бізнес-подорожуючих. Наш сучасний парк новітніх бізнес-джетів гарантує максимальний комфорт під час польотів.</value>
</data>
<data name="WelcomeSubtitle" xml:space="preserve">
<value>Ексклюзивні послуги з перельотів приватними джетами</value>
</data>
<data name="WelcomeTitle" xml:space="preserve">
<value>Ласкаво просимо до Sky Team Airlines</value>
</data>
<data name="FlightNumberLabel" xml:space="preserve">
<value>Номер рейсу</value>
</data>
<data name="ToLabel" xml:space="preserve">
<value>До</value>
</data>
<data name="PlaneLabel" xml:space="preserve">
<value>Літак</value>
</data>
<data name="BookButtonLabel" xml:space="preserve">
<value>Забронювати</value>
</data>
<data name="AvailableFlightsTitle" xml:space="preserve">
<value>Доступні рейси</value>
</data>
<data name="SelectFlightInstruction" xml:space="preserve">
<value>Виберіть рейс і натисніть «Забронювати»</value>
</data>
<data name="BookingIdLabel" xml:space="preserve">
<value>ID бронювання</value>
</data>
<data name="FlightNumberShortLabel" xml:space="preserve">
<value>№ рейсу</value>
</data>
<data name="StatusLabel" xml:space="preserve">
<value>Статус</value>
</data>
<data name="CancelFlightButton" xml:space="preserve">
<value>Скасувати рейс</value>
</data>
<data name="CreatePdfButton" xml:space="preserve">
<value>Експортувати у PDF</value>
</data>
</root>

View File

@@ -2,179 +2,156 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
Title="SettingsPage">
xmlns:properties="clr-namespace:SkyTeam"
Title="SettingsPage"
Background="{DynamicResource PageBackground}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0"
Grid.ColumnSpan="2"
Background="#FF1E88E5"
Padding="15">
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<Border Grid.Row="0" Grid.ColumnSpan="2" Background="#FF1E88E5" Padding="15">
<StackPanel Orientation="Horizontal">
<Ellipse Width="36" Height="36" Fill="White" Margin="0,0,10,0"/>
<StackPanel>
<TextBlock Text="Sky Team Airlines"
FontSize="20"
FontWeight="Bold"
Foreground="White"/>
<TextBlock Text="Sichere und komfortable Flüge weltweit"
FontSize="12"
Foreground="White"/>
<TextBlock Text="{x:Static properties:Resources.HeaderTitle}" FontSize="20" FontWeight="Bold" Foreground="White"/>
<TextBlock Text="{x:Static properties:Resources.HeaderSubtitle}" FontSize="12" Foreground="White"/>
</StackPanel>
</StackPanel>
</Border>
<StackPanel Grid.Row="1"
Grid.Column="0"
Background="#FFE3F2FD"
Orientation="Vertical">
<StackPanel Grid.Row="1" Grid.Column="0" Background="{DynamicResource SidebarBackground}">
<Button x:Name="HomeButton"
Height="50"
Margin="5"
Click="HomeButton_Click">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Home" Width="20" Height="20" Margin="0,0,10,0"/>
<TextBlock Text="Home"/>
<Button Height="50" Margin="5" Click="HomeButton_Click" Background="Transparent" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Home" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarHome}" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button x:Name="BookingsButton"
Height="50"
Margin="5"
Click="BookingsButton_Click">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Airplane" Width="20" Height="20" Margin="0,0,10,0"/>
<TextBlock Text="Meine Buchungen"/>
<Button Height="50" Margin="5" Click="BookingsButton_Click" Background="Transparent" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Airplane" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarBookings}" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button x:Name="SettingsButton"
Height="50"
Margin="5"
Click="SettingsButton_Click"
Background="#FFBBDEFB">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Cog" Width="20" Height="20" Margin="0,0,10,0"/>
<TextBlock Text="Einstellungen"/>
<Button Height="50" Margin="5" Background="{DynamicResource CardBackground}" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Cog" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarSettings}" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button x:Name="LogoutButton"
Height="50"
Margin="5"
Background="#FFEBEB"
BorderBrush="#FFB71C1C"
Foreground="#D32F2F"
FontWeight="Bold"
Click="LogoutButton_Click">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Logout" Width="20" Height="20" Margin="0,0,10,0"/>
<TextBlock Text="Abmelden"/>
<Button Height="50" Margin="5" Background="#FFEBEB" BorderBrush="#FFB71C1C" Foreground="#D32F2F" FontWeight="Bold" Click="LogoutButton_Click">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Logout" Width="20" Margin="0,0,10,0"/>
<TextBlock Text="{x:Static properties:Resources.SidebarLogout}"/>
</StackPanel>
</Button>
</StackPanel>
<Grid Grid.Row="1" Grid.Column="1" Margin="30">
<StackPanel>
<TextBlock Text="{x:Static properties:Resources.SidebarSettings}" FontSize="28" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.CustomizeExperience}" FontSize="16" Foreground="{DynamicResource SecondaryText}" Margin="0,0,0,25"/>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
Margin="0,0,0,25">
<iconPacks:PackIconMaterial Kind="Cog" Width="32" Height="32" Margin="0,0,12,0"/>
<StackPanel>
<TextBlock Text="Einstellungen"
FontSize="28"
FontWeight="Bold"/>
<TextBlock Text="Passen Sie Ihr Sky Team Erlebnis an"
FontSize="16"
Foreground="#666"/>
</StackPanel>
<Border Background="{DynamicResource CardBackground}" CornerRadius="12" Padding="25" Margin="0,0,0,25">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="ThemeLightDark" Width="32" Height="32" Foreground="{DynamicResource PrimaryText}" Margin="0,0,15,0"/>
<StackPanel VerticalAlignment="Center" Width="300">
<TextBlock Text="{x:Static properties:Resources.DarkMode}" FontSize="18" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.EnableDarkMode}" FontSize="14" Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<ToggleButton x:Name="DarkModeToggle" Width="60" Height="30" Checked="DarkModeToggle_Checked" Unchecked="DarkModeToggle_Unchecked">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border x:Name="Border" CornerRadius="15" Background="#E0E0E0" BorderBrush="#999" BorderThickness="1">
<Grid>
<Ellipse x:Name="Dot" Width="24" Height="24" HorizontalAlignment="Left" Margin="2,0,0,0" Fill="White">
<Ellipse.Effect>
<DropShadowEffect BlurRadius="4" ShadowDepth="1" Opacity="0.3"/>
</Ellipse.Effect>
</Ellipse>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Border" Property="Background" Value="#1E88E5"/>
<Setter TargetName="Dot" Property="HorizontalAlignment" Value="Right"/>
<Setter TargetName="Dot" Property="Margin" Value="0,0,2,0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
</StackPanel>
</Border>
<Border Background="{DynamicResource CardBackground}" CornerRadius="12" Padding="25" Margin="0,0,0,25">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="Translate"
Width="32"
Height="32"
Foreground="{DynamicResource PrimaryText}"
Margin="0,0,15,0"/>
<StackPanel Width="300">
<TextBlock Text="{x:Static properties:Resources.Language}"
FontSize="18"
FontWeight="Bold"
Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.ChooseLanguage}"
FontSize="14"
Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<ComboBox x:Name="LanguageComboBox"
Width="150"
SelectionChanged="LanguageComboBox_SelectionChanged">
<ComboBoxItem Content="Deutsch" Tag="de"/>
<ComboBoxItem Content="English" Tag="en"/>
<ComboBoxItem Content="Українська" Tag="uk"/>
<ComboBoxItem Content="العربية" Tag="ar"/>
</ComboBox>
</StackPanel>
</Border>
<Border Background="#FEF2F2" CornerRadius="12" Padding="25" BorderBrush="#EF5350" BorderThickness="1">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,15">
<iconPacks:PackIconMaterial Kind="Alert" Width="24" Height="24" Foreground="#D32F2F" Margin="0,0,10,0"/>
<TextBlock Text="{x:Static properties:Resources.DangerZone}" FontSize="20" FontWeight="Bold" Foreground="#D32F2F"/>
</StackPanel>
<TextBlock Text="{x:Static properties:Resources.DeleteAccountWarning}" FontSize="14" Foreground="#B71C1C" Margin="0,0,0,15"/>
<Button x:Name="DeleteAccountButton" Width="220" Height="45" Background="#D32F2F" Foreground="White" FontWeight="Bold" HorizontalAlignment="Left" Click="DeleteAccountButton_Click">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="AccountRemove" Width="20" Margin="0,0,10,0"/>
<TextBlock Text="{x:Static properties:Resources.DeleteAccount}"/>
</StackPanel>
</Button>
</StackPanel>
</Border>
</StackPanel>
<Border Background="White"
CornerRadius="12"
Padding="30"
BorderBrush="#E0E0E0"
BorderThickness="1"
Margin="0,0,0,25"
VerticalAlignment="Top">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<iconPacks:PackIconMaterial Kind="WeatherNight" Width="28" Height="28" Margin="0,0,15,0"/>
<StackPanel VerticalAlignment="Center">
<TextBlock Text="Dark Mode"
FontSize="18"
FontWeight="Bold"/>
<TextBlock Text="Aktivieren Sie den dunklen Modus für die Anwendung."
FontSize="14"
Foreground="#666"
Margin="0,4,0,0"/>
</StackPanel>
<ToggleButton x:Name="DarkModeToggle"
Width="90"
Height="36"
Margin="30,0,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Background="#F5F5F5"
BorderBrush="#DDD"
Content="Aus"
FontSize="14"
FontWeight="SemiBold"
Checked="DarkModeToggle_Checked"
Unchecked="DarkModeToggle_Unchecked"/>
</StackPanel>
</Border>
<Border Background="#FEF2F2"
CornerRadius="12"
Padding="30"
BorderBrush="#FFB71C1C"
BorderThickness="1">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,15">
<iconPacks:PackIconMaterial Kind="AlertCircle" Width="28" Height="28" Foreground="#D32F2F" Margin="0,0,12,0"/>
<StackPanel>
<TextBlock Text="Konto löschen"
FontSize="20"
FontWeight="Bold"
Foreground="#D32F2F"/>
<TextBlock Text="⚠️ Achtung: Diese Aktion kann nicht rückgängig gemacht werden!"
FontSize="14"
Foreground="#B71C1C"
Margin="0,5,0,0"/>
</StackPanel>
</StackPanel>
<Button x:Name="DeleteAccountButton"
Width="200"
Height="45"
HorizontalAlignment="Center"
Background="#D32F2F"
Foreground="White"
FontSize="15"
FontWeight="Bold"
Click="DeleteAccountButton_Click">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<iconPacks:PackIconMaterial Kind="AccountRemove" Width="20" Height="20" Margin="0,0,8,0"/>
<TextBlock Text="Konto endgültig löschen"/>
</StackPanel>
</Button>
</StackPanel>
</Border>
</Grid>
</Grid>
</Page>

View File

@@ -1,88 +1,129 @@
using System.Windows;
using MySql.Data.MySqlClient;
using System;
using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Navigation;
namespace SkyTeam
{
public partial class SettingsPage : Page
{
private bool _isDark = false;
public SettingsPage()
{
InitializeComponent();
// Quelle: Stack Overflow "How to compare SolidColorBrush in WPF"
// 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
var bgBrush = Application.Current.Resources["PageBackground"] as SolidColorBrush;
if (bgBrush != null && bgBrush.Color == Color.FromRgb(30, 30, 30))
{
DarkModeToggle.IsChecked = true;
DarkModeToggle.Content = "An";
}
else
{
DarkModeToggle.Content = "Aus";
}
}
private void DarkModeToggle_Checked(object sender, RoutedEventArgs e)
{
_isDark = true;
DarkModeToggle.Content = "An";
SetRes("PageBackground", Color.FromRgb(30, 30, 30));
SetRes("CardBackground", Color.FromRgb(45, 45, 45));
SetRes("SidebarBackground", Color.FromRgb(20, 20, 20));
SetRes("PrimaryText", Colors.White);
SetRes("SecondaryText", Color.FromRgb(200, 200, 200));
if (Window.GetWindow(this) is MainWindow mainWindow)
{
mainWindow.Background = Brushes.Black;
}
DarkModeToggle.Content = "An";
}
private void DarkModeToggle_Unchecked(object sender, RoutedEventArgs e)
{
_isDark = false;
SetRes("PageBackground", Colors.White);
SetRes("CardBackground", Color.FromRgb(245, 247, 250));
SetRes("SidebarBackground", Color.FromRgb(227, 242, 253));
SetRes("PrimaryText", Colors.Black);
SetRes("SecondaryText", Color.FromRgb(102, 102, 102));
DarkModeToggle.Content = "Aus";
if (Window.GetWindow(this) is MainWindow mainWindow)
{
mainWindow.Background = Brushes.White;
}
}
// Quelle: AI Assistant (chat gpt)
// Idee: Refactoring / DRY-Prinzip (Don't Repeat Yourself)
// 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.
private void SetRes(string key, Color color)
{
Application.Current.Resources[key] = new SolidColorBrush(color);
}
private void DeleteAccountButton_Click(object sender, RoutedEventArgs e)
{
var result = MessageBox.Show(
"Sind Sie sicher, dass Sie Ihr Konto löschen möchten?\nDiese Aktion kann nicht rückgängig gemacht werden!",
"Konto löschen",
MessageBoxButton.YesNo,
MessageBoxImage.Warning);
if (result == MessageBoxResult.Yes)
if (MessageBox.Show("Möchten Sie Ihr Konto wirklich löschen?\nAlle Buchungen werden ebenfalls gelöscht.", "Achtung", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
{
try
{
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
{
conn.Open();
// Quelle: Reddit - r/csharp "Best way to delete user with related data?"
// Aufgrund von Foreign Key Constraints in der Datenbank
// 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
string deleteBookings = "DELETE FROM buchungen WHERE UserId = @uid";
MySqlCommand cmd1 = new MySqlCommand(deleteBookings, conn);
cmd1.Parameters.AddWithValue("@uid", SessionManager.CurrentUserId);
cmd1.ExecuteNonQuery();
MessageBox.Show("Konto wurde gelöscht.", "Erfolg", MessageBoxButton.OK, MessageBoxImage.Information);
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new LogInPage());
string deleteUser = "DELETE FROM users WHERE Id = @uid";
MySqlCommand cmd2 = new MySqlCommand(deleteUser, conn);
cmd2.Parameters.AddWithValue("@uid", SessionManager.CurrentUserId);
cmd2.ExecuteNonQuery();
}
SessionManager.CurrentUserId = 0;
MessageBox.Show("Ihr Konto wurde erfolgreich gelöscht.");
NavigationService.Navigate(new LogInPage());
}
catch (Exception ex)
{
MessageBox.Show("Fehler beim Löschen: " + ex.Message);
}
}
}
private void HomeButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new NavigationPage());
}
private void BookingsButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new MeineBuchungenPage());
}
private void SettingsButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new SettingsPage());
}
private void BookFlightButton_Click(object sender, RoutedEventArgs e)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new MeineBuchungenPage());
}
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 SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
private void LogoutButton_Click(object sender, RoutedEventArgs e)
{
var result = MessageBox.Show(
"Möchten Sie sich wirklich abmelden?",
"Abmelden",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
SessionManager.CurrentUserId = 0;
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)
{
if (LanguageComboBox.SelectedItem is ComboBoxItem selectedItem)
{
((MainWindow)Application.Current.MainWindow).MainFrame.Navigate(new LogInPage());
string culture = selectedItem.Tag.ToString();
Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
if (culture == "ar")
this.FlowDirection = FlowDirection.RightToLeft;
else
this.FlowDirection = FlowDirection.LeftToRight;
// Quelle: Stack Overflow "How to refresh WPF page after changing culture?"
// Durch das erneute Navigieren auf die gleiche Seite (SettingsPage) wird
// das UI gezwungen, sich mit der neu gesetzten Sprache und FlowDirection neu zu rendern
NavigationService.Navigate(new SettingsPage());
}
}
}
}

View File

@@ -1,15 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<ApplicationIcon>icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Content Include="icon.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="MahApps.Metro.IconPacks" Version="6.2.1" />
<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>
<Compile Update="Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -1,75 +0,0 @@
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS fluege;
DROP TABLE IF EXISTS piloten;
DROP TABLE IF EXISTS flugzeuge;
DROP TABLE IF EXISTS mitarbeiter;
DROP TABLE IF EXISTS users;
SET FOREIGN_KEY_CHECKS = 1;
CREATE TABLE users (
Id INT AUTO_INCREMENT PRIMARY KEY,
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),
Anrede VARCHAR(20),
Geburtsdatum DATE,
CreatedAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE flugzeuge (
Id INT AUTO_INCREMENT PRIMARY KEY,
Modell VARCHAR(100) NOT NULL,
Plaetze INT 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 BOOLEAN NOT NULL
);
CREATE TABLE piloten (
Id INT AUTO_INCREMENT PRIMARY KEY,
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),
IstVerfuegbar BOOLEAN NOT NULL,
Sprachen TEXT
);
CREATE TABLE fluege (
Id INT AUTO_INCREMENT PRIMARY KEY,
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 NOT NULL,
PilotId INT NOT NULL,
ErstelltVon INT NOT NULL,
FOREIGN KEY (FlugzeugId) REFERENCES flugzeuge(Id),
FOREIGN KEY (PilotId) REFERENCES piloten(Id),
FOREIGN KEY (ErstelltVon) REFERENCES users(Id)
);
CREATE TABLE mitarbeiter (
Id INT AUTO_INCREMENT PRIMARY KEY,
Vorname VARCHAR(100) NOT NULL,
Nachname VARCHAR(100) NOT NULL,
Position VARCHAR(100) NOT NULL,
MitarbeiterAlter INT NOT NULL,
ArbeitsstundenProWoche FLOAT NOT NULL,
IstVerfuegbar BOOLEAN NOT NULL
);

315
SkyTeam/Tabellen.sql Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

209
SkyTeam/migration.sql Normal file
View 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;

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SkyTeam
{
class mitarbeiterRepo
{
}
}

View File

@@ -0,0 +1,164 @@
<Page x:Class="SkyTeam.ReservierungssuchePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:properties="clr-namespace:SkyTeam"
Title="ReservierungssuchePage"
Background="{DynamicResource PageBackground}">
<!--Implementierung mit Unterstützung durch ChatGPT
Datum: 17.02.2026
Prompt sinngemäß: Как реализовать многоязычный Placeholder для DatePickerTextBox в WPF с использованием ресурсов (.resx) и привязки к текущей CultureInfo, чтобы текст обновлялся при смене языка приложения?-->
<Page.Resources>
<!-- Style für Innertext DatePickerTextBox -->
<Style TargetType="DatePickerTextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DatePickerTextBox">
<Grid>
<ScrollViewer x:Name="PART_ContentHost"/>
<!-- placeholder -->
<TextBlock
Text="{x:Static properties:Resources.SelectDate}"
Foreground="Gray"
Margin="5,0,0,0"
VerticalAlignment="Center"
IsHitTestVisible="False"
Visibility="Collapsed"
x:Name="PlaceholderText"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Text" Value="">
<Setter TargetName="PlaceholderText"
Property="Visibility"
Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0" Grid.ColumnSpan="2" Background="#FF1E88E5" Padding="15">
<StackPanel Orientation="Horizontal">
<Ellipse Width="36" Height="36" Fill="White" Margin="0,0,10,0"/>
<StackPanel>
<TextBlock Text="{x:Static properties:Resources.HeaderTitle}" FontSize="20" FontWeight="Bold" Foreground="White"/>
<TextBlock Text="{x:Static properties:Resources.HeaderSubtitle}" FontSize="12" Foreground="White"/>
</StackPanel>
</StackPanel>
</Border>
<StackPanel Grid.Row="1" Grid.Column="0" Background="{DynamicResource SidebarBackground}">
<Button Height="50" Margin="5" Click="HomeButton_Click" Background="Transparent" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Home" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarHome}" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button Height="50" Margin="5" Click="BookingsButton_Click" Background="{DynamicResource CardBackground}" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Airplane" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarBookings}" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button Height="50" Margin="5" Click="SettingsButton_Click" Background="Transparent" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Cog" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarSettings}" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button Height="50" Margin="5" Background="#FFEBEB" BorderBrush="#FFB71C1C" Foreground="#D32F2F" FontWeight="Bold" Click="LogoutButton_Click">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Logout" Width="20" Margin="0,0,10,0"/>
<TextBlock Text="{x:Static properties:Resources.SidebarLogout}"/>
</StackPanel>
</Button>
</StackPanel>
<Grid Grid.Row="1" Grid.Column="1" Margin="30">
<StackPanel Margin="0,0,0,25">
<TextBlock Text="{x:Static properties:Resources.SearchFlights}" FontSize="28" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="Wählen Sie Ihr Ziel aus der Liste" FontSize="16" Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<Border Background="{DynamicResource CardBackground}" CornerRadius="12" Padding="30">
<StackPanel Width="350">
<TextBlock Text="{x:Static properties:Resources.PrepositionVon}" FontWeight="SemiBold" Margin="0,0,0,5" Foreground="{DynamicResource PrimaryText}"/>
<ComboBox x:Name="FromBox" Height="40" Margin="0,0,0,15" IsEditable="True">
<ComboBoxItem Content="Berlin"/>
<ComboBoxItem Content="München"/>
<ComboBoxItem Content="Frankfurt"/>
<ComboBoxItem Content="Hamburg"/>
<ComboBoxItem Content="Paris"/>
<ComboBoxItem Content="London"/>
<ComboBoxItem Content="Madrid"/>
<ComboBoxItem Content="Rom"/>
<ComboBoxItem Content="Lissabon"/>
<ComboBoxItem Content="Wien"/>
<ComboBoxItem Content="Zürich"/>
<ComboBoxItem Content="Amsterdam"/>
<ComboBoxItem Content="Prag"/>
<ComboBoxItem Content="Budapest"/>
<ComboBoxItem Content="Warschau"/>
<ComboBoxItem Content="Paderborn"/>
</ComboBox>
<TextBlock Text="{x:Static properties:Resources.To}" FontWeight="SemiBold" Margin="0,0,0,5" Foreground="{DynamicResource PrimaryText}"/>
<ComboBox x:Name="ToBox" Height="40" Margin="0,0,0,15" IsEditable="True">
<ComboBoxItem Content="Mallorca"/>
<ComboBoxItem Content="Berlin"/>
<ComboBoxItem Content="München"/>
<ComboBoxItem Content="Frankfurt"/>
<ComboBoxItem Content="Hamburg"/>
<ComboBoxItem Content="Paris"/>
<ComboBoxItem Content="London"/>
<ComboBoxItem Content="Madrid"/>
<ComboBoxItem Content="Rom"/>
<ComboBoxItem Content="Lissabon"/>
<ComboBoxItem Content="Wien"/>
<ComboBoxItem Content="Zürich"/>
<ComboBoxItem Content="Amsterdam"/>
<ComboBoxItem Content="Prag"/>
<ComboBoxItem Content="Budapest"/>
<ComboBoxItem Content="Tokio"/>
<ComboBoxItem Content="New York"/>
<ComboBoxItem Content="Dubai"/>
</ComboBox>
<TextBlock Text="{x:Static properties:Resources.DepartureDate}" FontWeight="SemiBold" Margin="0,0,0,5" Foreground="{DynamicResource PrimaryText}"/>
<DatePicker x:Name="DateBox" Height="40" Margin="0,0,0,25"/>
<Button Content="{x:Static properties:Resources.SearchFlights}"
Height="45"
FontWeight="Bold"
Background="#FF1E88E5"
Foreground="White"
Click="SearchFlights_Click"/>
</StackPanel>
</Border>
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,34 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace SkyTeam
{
public partial class ReservierungssuchePage : Page
{
public ReservierungssuchePage()
{
InitializeComponent();
}
private void SearchFlights_Click(object sender, RoutedEventArgs e)
{
string from = FromBox.Text;
string to = ToBox.Text;
DateTime? date = DateBox.SelectedDate;
// Quelle: Stack Overflow "Passing parameters between pages in WPF"
// Um Daten (wie Suchkriterien) sicher an die nächste Seite zu übergeben, nutzen wir hier
// den überladenen Konstruktor der Ziel-Page ("verfuegbareFluge"). Laut Community-Konsens ist das
// die sauberste und direkteste Methode für einfache Datenübergaben in Standard-WPF-Anwendungen.
NavigationService.Navigate(new verfuegbareFluge(from, to, date));
}
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 SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
private void LogoutButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new LogInPage());
}
}

View File

@@ -6,8 +6,10 @@ using System.Threading.Tasks;
namespace SkyTeam
{
class session
static class SessionManager
{
int selectedId { get; set; }
public static int CurrentUserId { get; set; }
public static string CurrentUserName { get; set; }
public static string Role { get; set; }
}
}

View File

@@ -0,0 +1,105 @@
<Page x:Class="SkyTeam.verfuegbareFluge"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:properties="clr-namespace:SkyTeam"
Title="verfuegbareFluge"
Background="{DynamicResource PageBackground}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0" Grid.ColumnSpan="2" Background="#FF1E88E5" Padding="15">
<StackPanel Orientation="Horizontal">
<Ellipse Width="36" Height="36" Fill="White" Margin="0,0,10,0"/>
<StackPanel>
<TextBlock Text="{x:Static properties:Resources.HeaderTitle}" FontSize="20" FontWeight="Bold" Foreground="White"/>
<TextBlock Text="{x:Static properties:Resources.HeaderSubtitle}" FontSize="12" Foreground="White"/>
</StackPanel>
</StackPanel>
</Border>
<StackPanel Grid.Row="1" Grid.Column="0" Background="{DynamicResource SidebarBackground}">
<Button Height="50" Margin="5" Click="HomeButton_Click" Background="Transparent" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Home" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarHome}" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button Height="50" Margin="5" Click="BookingsButton_Click" Background="{DynamicResource CardBackground}" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Airplane" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarBookings}" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button Height="50" Margin="5" Click="SettingsButton_Click" Background="Transparent" BorderThickness="0">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Cog" Width="20" Margin="0,0,10,0" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SidebarSettings}" Foreground="{DynamicResource PrimaryText}"/>
</StackPanel>
</Button>
<Button Height="50" Margin="5" Background="#FFEBEB" BorderBrush="#FFB71C1C" Foreground="#D32F2F" FontWeight="Bold" Click="LogoutButton_Click">
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Logout" Width="20" Margin="0,0,10,0"/>
<TextBlock Text="{x:Static properties:Resources.SidebarLogout}"/>
</StackPanel>
</Button>
</StackPanel>
<Grid Grid.Row="1" Grid.Column="1" Margin="30">
<StackPanel Margin="0,0,0,25">
<TextBlock Text="{x:Static properties:Resources.AvailableFlightsTitle}" FontSize="28" FontWeight="Bold" Foreground="{DynamicResource PrimaryText}"/>
<TextBlock Text="{x:Static properties:Resources.SelectFlightInstruction}" FontSize="16" Foreground="{DynamicResource SecondaryText}"/>
</StackPanel>
<Border Background="{DynamicResource CardBackground}" CornerRadius="12" Padding="20">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid x:Name="AvailableFlightsDataGrid"
Grid.Row="0"
AutoGenerateColumns="False"
CanUserAddRows="False"
IsReadOnly="True"
GridLinesVisibility="Horizontal"
HeadersVisibility="Column"
SelectionMode="Single"
Margin="0,0,0,20">
<DataGrid.Columns>
<DataGridTextColumn Header="{x:Static properties:Resources.FlightNumberLabel}" Width="120" Binding="{Binding FlightNumber}"/>
<DataGridTextColumn Header="{x:Static properties:Resources.PrepositionVon}" Width="100" Binding="{Binding From}"/>
<DataGridTextColumn Header="{x:Static properties:Resources.ToLabel}" Width="100" Binding="{Binding To}"/>
<DataGridTextColumn Header="{x:Static properties:Resources.PilotLabel}" Width="120" Binding="{Binding Pilot}"/>
<DataGridTextColumn Header="{x:Static properties:Resources.PlaneLabel}" Width="120" Binding="{Binding Plane}"/>
<DataGridTextColumn Header="{x:Static properties:Resources.DateLabel}" Width="140" Binding="{Binding Date}"/>
</DataGrid.Columns>
</DataGrid>
<Button Grid.Row="1"
Content="{x:Static properties:Resources.BookButtonLabel}"
Height="45"
Width="140"
HorizontalAlignment="Right"
Background="#FF1E88E5"
Foreground="White"
FontWeight="Bold"
Click="BookFlight_Click"/>
</Grid>
</Border>
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,126 @@
using System;
using System.Data;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using MySql.Data.MySqlClient;
namespace SkyTeam
{
public partial class verfuegbareFluge : Page
{
private string _fromCity;
private string _toCity;
private DateTime? _flightDate;
public verfuegbareFluge(string from = "", string to = "", DateTime? date = null)
{
InitializeComponent();
_fromCity = from;
_toCity = to;
_flightDate = date;
LoadFlights();
}
private void LoadFlights()
{
string query = @"SELECT f.Id, f.Flugnummer, f.Abflugort AS 'From', f.Zielort AS 'To',
z.Modell AS Plane, f.Abflugdatum AS Date
FROM fluege f
JOIN flugzeuge z ON f.FlugzeugId = z.Id
WHERE 1=1";
if (!string.IsNullOrWhiteSpace(_fromCity))
{
query += " AND f.Abflugort LIKE @from";
}
if (!string.IsNullOrWhiteSpace(_toCity))
{
query += " AND f.Zielort LIKE @to";
}
if (_flightDate.HasValue)
{
query += " AND DATE(f.Abflugdatum) = @date";
}
try
{
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
{
conn.Open();
MySqlCommand cmd = new MySqlCommand(query, conn);
if (!string.IsNullOrWhiteSpace(_fromCity))
cmd.Parameters.AddWithValue("@from", "%" + _fromCity + "%");
if (!string.IsNullOrWhiteSpace(_toCity))
cmd.Parameters.AddWithValue("@to", "%" + _toCity + "%");
if (_flightDate.HasValue)
cmd.Parameters.AddWithValue("@date", _flightDate.Value.ToString("yyyy-MM-dd"));
MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
adapter.Fill(dt);
AvailableFlightsDataGrid.ItemsSource = dt.DefaultView;
if (dt.Rows.Count == 0)
{
MessageBox.Show("Keine Flüge gefunden.");
}
}
}
catch (Exception ex)
{
MessageBox.Show("Fehler beim Laden: " + ex.Message);
}
}
private void BookFlight_Click(object sender, RoutedEventArgs e)
{
if (AvailableFlightsDataGrid.SelectedItem == null)
{
MessageBox.Show("Bitte wählen Sie einen Flug aus!");
return;
}
// Source: Stack Overflow "Get selected row item in DataGrid WPF"
DataRowView row = (DataRowView)AvailableFlightsDataGrid.SelectedItem;
int flightId = Convert.ToInt32(row["Id"]);
if (SessionManager.CurrentUserId == 0)
{
MessageBox.Show("Fehler: Nicht eingeloggt.");
return;
}
string query = "INSERT INTO buchungen (UserId, FlugId) VALUES (@uid, @fid)";
try
{
using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection()))
{
conn.Open();
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@uid", SessionManager.CurrentUserId);
cmd.Parameters.AddWithValue("@fid", flightId);
cmd.ExecuteNonQuery();
}
MessageBox.Show("Erfolgreich gebucht!");
NavigationService.Navigate(new BuchungenPage());
}
catch (Exception ex)
{
MessageBox.Show("Fehler: " + ex.Message);
}
}
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 SettingsButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new SettingsPage());
private void LogoutButton_Click(object sender, RoutedEventArgs e) => NavigationService.Navigate(new LogInPage());
}
}

BIN
Titel.docx Normal file

Binary file not shown.

1
connectionstring.txt Normal file
View File

@@ -0,0 +1 @@
Server=mysql.pb.bib.de;uid=pbt3h24akh;pwd=Dd3dwQgPeNxW;database=pbt3h24akh_SkyTeam;