commit b8f9c55b666c4122b54d4880b402180d4076e47b Author: Giovanny BRUNET Date: Thu Apr 3 15:53:45 2025 +0200 Commit initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3fb3cad --- /dev/null +++ b/.gitignore @@ -0,0 +1,67 @@ +# ------------------------------- +# Fichiers et dossiers spécifiques à Visual Studio / Rider +# ------------------------------- +.vs/ +.vscode/ +.idea/ +*.suo +*.user +*.userosscache +*.sln.docstates + +# ------------------------------- +# Fichiers de build et dossiers de sortie +# ------------------------------- +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# ------------------------------- +# Fichiers NuGet +# ------------------------------- +*.nupkg +*.nuspec +packages/ +.nuget/ + +# ------------------------------- +# Fichiers de cache et temporaires +# ------------------------------- +*.cache +*.temp +*.tmp +*.log + +# ------------------------------- +# Spécifique aux plateformes MAUI +# ------------------------------- + +## Android +android/app/build/ +android/.gradle/ +android/local.properties + +## iOS +ios/obj/ +ios/bin/ + +## MacCatalyst +maccatalyst/obj/ +maccatalyst/bin/ + +## Windows +windows/obj/ +windows/bin/ + +# ------------------------------- +# Fichiers de déploiement +# ------------------------------- +*.apk +*.aab +*.ipa + +# ------------------------------- +# Dossiers de résultats de tests +# ------------------------------- +TestResults/ diff --git a/MauiAppStock.sln b/MauiAppStock.sln new file mode 100644 index 0000000..6d69697 --- /dev/null +++ b/MauiAppStock.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MauiAppStock", "MauiAppStock\MauiAppStock.csproj", "{C70F5056-478B-49C0-AA49-2F10F14D92F5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C70F5056-478B-49C0-AA49-2F10F14D92F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C70F5056-478B-49C0-AA49-2F10F14D92F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C70F5056-478B-49C0-AA49-2F10F14D92F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C70F5056-478B-49C0-AA49-2F10F14D92F5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/MauiAppStock/.gitignore b/MauiAppStock/.gitignore new file mode 100644 index 0000000..3fb3cad --- /dev/null +++ b/MauiAppStock/.gitignore @@ -0,0 +1,67 @@ +# ------------------------------- +# Fichiers et dossiers spécifiques à Visual Studio / Rider +# ------------------------------- +.vs/ +.vscode/ +.idea/ +*.suo +*.user +*.userosscache +*.sln.docstates + +# ------------------------------- +# Fichiers de build et dossiers de sortie +# ------------------------------- +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# ------------------------------- +# Fichiers NuGet +# ------------------------------- +*.nupkg +*.nuspec +packages/ +.nuget/ + +# ------------------------------- +# Fichiers de cache et temporaires +# ------------------------------- +*.cache +*.temp +*.tmp +*.log + +# ------------------------------- +# Spécifique aux plateformes MAUI +# ------------------------------- + +## Android +android/app/build/ +android/.gradle/ +android/local.properties + +## iOS +ios/obj/ +ios/bin/ + +## MacCatalyst +maccatalyst/obj/ +maccatalyst/bin/ + +## Windows +windows/obj/ +windows/bin/ + +# ------------------------------- +# Fichiers de déploiement +# ------------------------------- +*.apk +*.aab +*.ipa + +# ------------------------------- +# Dossiers de résultats de tests +# ------------------------------- +TestResults/ diff --git a/MauiAppStock/App.xaml b/MauiAppStock/App.xaml new file mode 100644 index 0000000..2a0cdde --- /dev/null +++ b/MauiAppStock/App.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/MauiAppStock/App.xaml.cs b/MauiAppStock/App.xaml.cs new file mode 100644 index 0000000..7bb788a --- /dev/null +++ b/MauiAppStock/App.xaml.cs @@ -0,0 +1,20 @@ +using MauiAppStock.Data; +using MauiAppStock.Views; + +namespace MauiAppStock; + +public partial class App : Application +{ + public App() + { + InitializeComponent(); + // On démarre sur MainPage dans une NavigationPage pour permettre la navigation + MainPage = new NavigationPage(new MainPage()); + InitializeDatabase(); + } + + private async void InitializeDatabase() + { + await Database.InitializeAsync(); + } +} \ No newline at end of file diff --git a/MauiAppStock/AppShell.xaml b/MauiAppStock/AppShell.xaml new file mode 100644 index 0000000..bc2c2d4 --- /dev/null +++ b/MauiAppStock/AppShell.xaml @@ -0,0 +1,16 @@ + + + + + + diff --git a/MauiAppStock/AppShell.xaml.cs b/MauiAppStock/AppShell.xaml.cs new file mode 100644 index 0000000..5a5c839 --- /dev/null +++ b/MauiAppStock/AppShell.xaml.cs @@ -0,0 +1,9 @@ +namespace MauiAppStock; + +public partial class AppShell : Shell +{ + public AppShell() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/MauiAppStock/Data/Database.cs b/MauiAppStock/Data/Database.cs new file mode 100644 index 0000000..844953c --- /dev/null +++ b/MauiAppStock/Data/Database.cs @@ -0,0 +1,143 @@ +using SQLite; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using MauiAppStock.Models; + +namespace MauiAppStock.Data +{ + public class Database + { + private static SingletonConnection db; + + public static async Task InitializeAsync() + { + if (db == null) + { + string dbPath = Path.Combine(FileSystem.AppDataDirectory, "MauiAppStock.db3"); + db = SingletonConnection.GetInstance(dbPath); + // Création des tables si elles n'existent pas + await db.CreateTableAsync(); + await db.CreateTableAsync(); + await db.CreateTableAsync(); // Table de liaison + } + } + + // CRUD pour Appareil + public static Task AddAppareilAsync(Appareil appareil) + { + return db.InsertAsync(appareil); + } + + public static Task> GetAppareilsAsync() + { + return db.Table().ToListAsync(); + } + + public static Task UpdateAppareilAsync(Appareil appareil) + { + return db.UpdateAsync(appareil); + } + + public static Task DeleteAppareilAsync(Appareil appareil) + { + return db.DeleteAsync(appareil); + } + + // CRUD pour Piece + public static Task AddPieceAsync(Piece piece) + { + return db.InsertAsync(piece); + } + + public static Task> GetPiecesAsync() + { + return db.Table().ToListAsync(); + } + + public static Task UpdatePieceAsync(Piece piece) + { + return db.UpdateAsync(piece); + } + + public static Task DeletePieceAsync(Piece piece) + { + return db.DeleteAsync(piece); + } + + // Liaison entre Appareil et Piece + public static Task AddAppareilPieceAsync(AppareilPiece appareilPiece) + { + return db.InsertAsync(appareilPiece); + } + + // Met à jour une association existante + public static Task UpdateAppareilPieceAsync(AppareilPiece appareilPiece) + { + return db.UpdateAsync(appareilPiece); + } + + // Supprime une association existante + public static Task DeleteAppareilPieceAsync(AppareilPiece appareilPiece) + { + return db.DeleteAsync(appareilPiece); + } + + // Récupérer toutes les pièces associées à un appareil + public static async Task> GetPiecesForAppareilAsync(int appareilId) + { + var associations = await db.Table().Where(ap => ap.AppareilId == appareilId).ToListAsync(); + var pieces = new List(); + foreach (var assoc in associations) + { + var piece = await db.Table().Where(p => p.Id == assoc.PieceId).FirstOrDefaultAsync(); + if (piece != null) + { + // Assigner le flag de recommandation provenant de la table de liaison + piece.EstRecommandee = assoc.EstRecommandee; + pieces.Add(piece); + } + } + // Trier pour que les pièces recommandées apparaissent en premier + return pieces.OrderByDescending(p => p.EstRecommandee).ToList(); + } + + // Récupérer uniquement les pièces recommandées pour un appareil + public static async Task> GetPiecesRecommandeesForAppareilAsync(int appareilId) + { + var associations = await db.Table() + .Where(ap => ap.AppareilId == appareilId && ap.EstRecommandee) + .ToListAsync(); + var pieces = new List(); + foreach (var assoc in associations) + { + var piece = await db.Table().Where(p => p.Id == assoc.PieceId).FirstOrDefaultAsync(); + if (piece != null) + pieces.Add(piece); + } + return pieces; + } + + public static async Task> GetAppareilPiecesForAppareilAsync(int appareilId) + { + var associations = await db.Table().Where(ap => ap.AppareilId == appareilId).ToListAsync(); + foreach (var assoc in associations) + { + var piece = await db.Table().Where(p => p.Id == assoc.PieceId).FirstOrDefaultAsync(); + if (piece != null) + { + assoc.NomPiece = piece.Nom; + assoc.DescriptionPiece = piece.Description; + } + } + return associations.OrderByDescending(a => a.EstRecommandee).ToList(); + } + + public static async Task GetAppareilPieceAsync(int appareilId, int pieceId) + { + return await db.Table() + .Where(ap => ap.AppareilId == appareilId && ap.PieceId == pieceId) + .FirstOrDefaultAsync(); + } + } +} diff --git a/MauiAppStock/Data/SingletonConnection.cs b/MauiAppStock/Data/SingletonConnection.cs new file mode 100644 index 0000000..5cfe913 --- /dev/null +++ b/MauiAppStock/Data/SingletonConnection.cs @@ -0,0 +1,23 @@ +using SQLite; +using System.IO; + +namespace MauiAppStock.Data +{ + public class SingletonConnection : SQLiteAsyncConnection + { + private static SingletonConnection instance; + + private SingletonConnection(string dbPath) : base(dbPath) + { + } + + public static SingletonConnection GetInstance(string dbPath) + { + if (instance == null) + { + instance = new SingletonConnection(dbPath); + } + return instance; + } + } +} \ No newline at end of file diff --git a/MauiAppStock/Helpers/AsyncCommand.cs b/MauiAppStock/Helpers/AsyncCommand.cs new file mode 100644 index 0000000..3d69b58 --- /dev/null +++ b/MauiAppStock/Helpers/AsyncCommand.cs @@ -0,0 +1,86 @@ +using System; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace MauiAppStock.Helpers +{ + public class AsyncCommand : ICommand + { + private readonly Func _execute; + private readonly Func _canExecute; + private bool _isExecuting; + + public AsyncCommand(Func execute, Func canExecute = null) + { + _execute = execute ?? throw new ArgumentNullException(nameof(execute)); + _canExecute = canExecute; + } + + public bool CanExecute(object parameter) + { + return !_isExecuting && (_canExecute?.Invoke() ?? true); + } + + public async void Execute(object parameter) + { + if (!CanExecute(parameter)) + return; + + try + { + _isExecuting = true; + RaiseCanExecuteChanged(); + await _execute(); + } + finally + { + _isExecuting = false; + RaiseCanExecuteChanged(); + } + } + + public event EventHandler CanExecuteChanged; + public void RaiseCanExecuteChanged() => + CanExecuteChanged?.Invoke(this, EventArgs.Empty); + } + + public class AsyncCommand : ICommand + { + private readonly Func _execute; + private readonly Predicate _canExecute; + private bool _isExecuting; + + public AsyncCommand(Func execute, Predicate canExecute = null) + { + _execute = execute ?? throw new ArgumentNullException(nameof(execute)); + _canExecute = canExecute; + } + + public bool CanExecute(object parameter) + { + return !_isExecuting && (_canExecute?.Invoke((T)parameter) ?? true); + } + + public async void Execute(object parameter) + { + if (!CanExecute(parameter)) + return; + + try + { + _isExecuting = true; + RaiseCanExecuteChanged(); + await _execute((T)parameter); + } + finally + { + _isExecuting = false; + RaiseCanExecuteChanged(); + } + } + + public event EventHandler CanExecuteChanged; + public void RaiseCanExecuteChanged() => + CanExecuteChanged?.Invoke(this, EventArgs.Empty); + } +} diff --git a/MauiAppStock/MauiAppStock.csproj b/MauiAppStock/MauiAppStock.csproj new file mode 100644 index 0000000..11989d2 --- /dev/null +++ b/MauiAppStock/MauiAppStock.csproj @@ -0,0 +1,66 @@ + + + + net8.0-android;net8.0-ios;net8.0-maccatalyst + $(TargetFrameworks);net8.0-windows10.0.19041.0 + + + + + + + Exe + MauiAppStock + true + true + enable + enable + + + MauiAppStock + + + com.companyname.mauiappstock + + + 1.0 + 1 + + 11.0 + 13.1 + 21.0 + 10.0.17763.0 + 10.0.17763.0 + 6.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MauiAppStock/MauiProgram.cs b/MauiAppStock/MauiProgram.cs new file mode 100644 index 0000000..18d948e --- /dev/null +++ b/MauiAppStock/MauiProgram.cs @@ -0,0 +1,24 @@ +using Microsoft.Extensions.Logging; + +namespace MauiAppStock; + +public static class MauiProgram +{ + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + builder + .UseMauiApp() + .ConfigureFonts(fonts => + { + fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); + fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); + }); + +#if DEBUG + builder.Logging.AddDebug(); +#endif + + return builder.Build(); + } +} \ No newline at end of file diff --git a/MauiAppStock/Models/Appareil.cs b/MauiAppStock/Models/Appareil.cs new file mode 100644 index 0000000..e1bca2e --- /dev/null +++ b/MauiAppStock/Models/Appareil.cs @@ -0,0 +1,13 @@ +using SQLite; + +namespace MauiAppStock.Models +{ + public class Appareil + { + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + public string Nom { get; set; } + public string Description { get; set; } + // Vous pouvez ajouter d'autres propriétés (stock, historique, etc.) + } +} \ No newline at end of file diff --git a/MauiAppStock/Models/AppareilPiece.cs b/MauiAppStock/Models/AppareilPiece.cs new file mode 100644 index 0000000..2f1b16d --- /dev/null +++ b/MauiAppStock/Models/AppareilPiece.cs @@ -0,0 +1,18 @@ +using SQLite; + +namespace MauiAppStock.Models +{ + public class AppareilPiece + { + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + public int AppareilId { get; set; } + public int PieceId { get; set; } + public bool EstRecommandee { get; set; } + + [Ignore] + public string NomPiece { get; set; } + [Ignore] + public string DescriptionPiece { get; set; } + } +} \ No newline at end of file diff --git a/MauiAppStock/Models/Piece.cs b/MauiAppStock/Models/Piece.cs new file mode 100644 index 0000000..3de67ac --- /dev/null +++ b/MauiAppStock/Models/Piece.cs @@ -0,0 +1,18 @@ +using SQLite; + +namespace MauiAppStock.Models +{ + public class Piece + { + [PrimaryKey, AutoIncrement] + public int Id { get; set; } + public string Nom { get; set; } + public string Description { get; set; } + public double Prix { get; set; } + public int Stock { get; set; } + public string Fournisseur { get; set; } + + [Ignore] + public bool EstRecommandee { get; set; } + } +} \ No newline at end of file diff --git a/MauiAppStock/Platforms/Android/AndroidManifest.xml b/MauiAppStock/Platforms/Android/AndroidManifest.xml new file mode 100644 index 0000000..e9937ad --- /dev/null +++ b/MauiAppStock/Platforms/Android/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/MauiAppStock/Platforms/Android/MainActivity.cs b/MauiAppStock/Platforms/Android/MainActivity.cs new file mode 100644 index 0000000..75432bb --- /dev/null +++ b/MauiAppStock/Platforms/Android/MainActivity.cs @@ -0,0 +1,12 @@ +using Android.App; +using Android.Content.PM; +using Android.OS; + +namespace MauiAppStock; + +[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, + ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | + ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] +public class MainActivity : MauiAppCompatActivity +{ +} \ No newline at end of file diff --git a/MauiAppStock/Platforms/Android/MainApplication.cs b/MauiAppStock/Platforms/Android/MainApplication.cs new file mode 100644 index 0000000..f1e1179 --- /dev/null +++ b/MauiAppStock/Platforms/Android/MainApplication.cs @@ -0,0 +1,15 @@ +using Android.App; +using Android.Runtime; + +namespace MauiAppStock; + +[Application] +public class MainApplication : MauiApplication +{ + public MainApplication(IntPtr handle, JniHandleOwnership ownership) + : base(handle, ownership) + { + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} \ No newline at end of file diff --git a/MauiAppStock/Platforms/Android/Resources/values/colors.xml b/MauiAppStock/Platforms/Android/Resources/values/colors.xml new file mode 100644 index 0000000..c04d749 --- /dev/null +++ b/MauiAppStock/Platforms/Android/Resources/values/colors.xml @@ -0,0 +1,6 @@ + + + #512BD4 + #2B0B98 + #2B0B98 + \ No newline at end of file diff --git a/MauiAppStock/Platforms/MacCatalyst/AppDelegate.cs b/MauiAppStock/Platforms/MacCatalyst/AppDelegate.cs new file mode 100644 index 0000000..0ec9df2 --- /dev/null +++ b/MauiAppStock/Platforms/MacCatalyst/AppDelegate.cs @@ -0,0 +1,9 @@ +using Foundation; + +namespace MauiAppStock; + +[Register("AppDelegate")] +public class AppDelegate : MauiUIApplicationDelegate +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} \ No newline at end of file diff --git a/MauiAppStock/Platforms/MacCatalyst/Entitlements.plist b/MauiAppStock/Platforms/MacCatalyst/Entitlements.plist new file mode 100644 index 0000000..de4adc9 --- /dev/null +++ b/MauiAppStock/Platforms/MacCatalyst/Entitlements.plist @@ -0,0 +1,14 @@ + + + + + + + com.apple.security.app-sandbox + + + com.apple.security.network.client + + + + diff --git a/MauiAppStock/Platforms/MacCatalyst/Info.plist b/MauiAppStock/Platforms/MacCatalyst/Info.plist new file mode 100644 index 0000000..7268977 --- /dev/null +++ b/MauiAppStock/Platforms/MacCatalyst/Info.plist @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + UIDeviceFamily + + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + + diff --git a/MauiAppStock/Platforms/MacCatalyst/Program.cs b/MauiAppStock/Platforms/MacCatalyst/Program.cs new file mode 100644 index 0000000..f845ca5 --- /dev/null +++ b/MauiAppStock/Platforms/MacCatalyst/Program.cs @@ -0,0 +1,15 @@ +using ObjCRuntime; +using UIKit; + +namespace MauiAppStock; + +public class Program +{ + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppDelegate)); + } +} \ No newline at end of file diff --git a/MauiAppStock/Platforms/Tizen/Main.cs b/MauiAppStock/Platforms/Tizen/Main.cs new file mode 100644 index 0000000..3b85b4e --- /dev/null +++ b/MauiAppStock/Platforms/Tizen/Main.cs @@ -0,0 +1,16 @@ +using System; +using Microsoft.Maui; +using Microsoft.Maui.Hosting; + +namespace MauiAppStock; + +class Program : MauiApplication +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + + static void Main(string[] args) + { + var app = new Program(); + app.Run(args); + } +} \ No newline at end of file diff --git a/MauiAppStock/Platforms/Tizen/tizen-manifest.xml b/MauiAppStock/Platforms/Tizen/tizen-manifest.xml new file mode 100644 index 0000000..483ea82 --- /dev/null +++ b/MauiAppStock/Platforms/Tizen/tizen-manifest.xml @@ -0,0 +1,15 @@ + + + + + + maui-appicon-placeholder + + + + + http://tizen.org/privilege/internet + + + + \ No newline at end of file diff --git a/MauiAppStock/Platforms/Windows/App.xaml b/MauiAppStock/Platforms/Windows/App.xaml new file mode 100644 index 0000000..bd8b9b0 --- /dev/null +++ b/MauiAppStock/Platforms/Windows/App.xaml @@ -0,0 +1,8 @@ + + + diff --git a/MauiAppStock/Platforms/Windows/App.xaml.cs b/MauiAppStock/Platforms/Windows/App.xaml.cs new file mode 100644 index 0000000..f2af41c --- /dev/null +++ b/MauiAppStock/Platforms/Windows/App.xaml.cs @@ -0,0 +1,23 @@ +using Microsoft.UI.Xaml; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace MauiAppStock.WinUI; + +/// +/// Provides application-specific behavior to supplement the default Application class. +/// +public partial class App : MauiWinUIApplication +{ + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + this.InitializeComponent(); + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} \ No newline at end of file diff --git a/MauiAppStock/Platforms/Windows/Package.appxmanifest b/MauiAppStock/Platforms/Windows/Package.appxmanifest new file mode 100644 index 0000000..d73b13a --- /dev/null +++ b/MauiAppStock/Platforms/Windows/Package.appxmanifest @@ -0,0 +1,46 @@ + + + + + + + + + $placeholder$ + User Name + $placeholder$.png + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MauiAppStock/Platforms/Windows/app.manifest b/MauiAppStock/Platforms/Windows/app.manifest new file mode 100644 index 0000000..137127d --- /dev/null +++ b/MauiAppStock/Platforms/Windows/app.manifest @@ -0,0 +1,15 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/MauiAppStock/Platforms/iOS/AppDelegate.cs b/MauiAppStock/Platforms/iOS/AppDelegate.cs new file mode 100644 index 0000000..0ec9df2 --- /dev/null +++ b/MauiAppStock/Platforms/iOS/AppDelegate.cs @@ -0,0 +1,9 @@ +using Foundation; + +namespace MauiAppStock; + +[Register("AppDelegate")] +public class AppDelegate : MauiUIApplicationDelegate +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} \ No newline at end of file diff --git a/MauiAppStock/Platforms/iOS/Info.plist b/MauiAppStock/Platforms/iOS/Info.plist new file mode 100644 index 0000000..0004a4f --- /dev/null +++ b/MauiAppStock/Platforms/iOS/Info.plist @@ -0,0 +1,32 @@ + + + + + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + + diff --git a/MauiAppStock/Platforms/iOS/Program.cs b/MauiAppStock/Platforms/iOS/Program.cs new file mode 100644 index 0000000..f845ca5 --- /dev/null +++ b/MauiAppStock/Platforms/iOS/Program.cs @@ -0,0 +1,15 @@ +using ObjCRuntime; +using UIKit; + +namespace MauiAppStock; + +public class Program +{ + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppDelegate)); + } +} \ No newline at end of file diff --git a/MauiAppStock/Platforms/iOS/Resources/PrivacyInfo.xcprivacy b/MauiAppStock/Platforms/iOS/Resources/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..24ab3b4 --- /dev/null +++ b/MauiAppStock/Platforms/iOS/Resources/PrivacyInfo.xcprivacy @@ -0,0 +1,51 @@ + + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryDiskSpace + NSPrivacyAccessedAPITypeReasons + + E174.1 + + + + + + diff --git a/MauiAppStock/Properties/launchSettings.json b/MauiAppStock/Properties/launchSettings.json new file mode 100644 index 0000000..edf8aad --- /dev/null +++ b/MauiAppStock/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Windows Machine": { + "commandName": "MsixPackage", + "nativeDebugging": false + } + } +} \ No newline at end of file diff --git a/MauiAppStock/Resources/AppIcon/appicon.svg b/MauiAppStock/Resources/AppIcon/appicon.svg new file mode 100644 index 0000000..9d63b65 --- /dev/null +++ b/MauiAppStock/Resources/AppIcon/appicon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/MauiAppStock/Resources/AppIcon/appiconfg.svg b/MauiAppStock/Resources/AppIcon/appiconfg.svg new file mode 100644 index 0000000..21dfb25 --- /dev/null +++ b/MauiAppStock/Resources/AppIcon/appiconfg.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/MauiAppStock/Resources/Fonts/OpenSans-Regular.ttf b/MauiAppStock/Resources/Fonts/OpenSans-Regular.ttf new file mode 100644 index 0000000..2291fcb Binary files /dev/null and b/MauiAppStock/Resources/Fonts/OpenSans-Regular.ttf differ diff --git a/MauiAppStock/Resources/Fonts/OpenSans-Semibold.ttf b/MauiAppStock/Resources/Fonts/OpenSans-Semibold.ttf new file mode 100644 index 0000000..3cbe2f8 Binary files /dev/null and b/MauiAppStock/Resources/Fonts/OpenSans-Semibold.ttf differ diff --git a/MauiAppStock/Resources/Images/dotnet_bot.png b/MauiAppStock/Resources/Images/dotnet_bot.png new file mode 100644 index 0000000..f93ce02 Binary files /dev/null and b/MauiAppStock/Resources/Images/dotnet_bot.png differ diff --git a/MauiAppStock/Resources/Raw/AboutAssets.txt b/MauiAppStock/Resources/Raw/AboutAssets.txt new file mode 100644 index 0000000..89dc758 --- /dev/null +++ b/MauiAppStock/Resources/Raw/AboutAssets.txt @@ -0,0 +1,15 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories). Deployment of the asset to your application +is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. + + + +These files will be deployed with your package and will be accessible using Essentials: + + async Task LoadMauiAsset() + { + using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); + using var reader = new StreamReader(stream); + + var contents = reader.ReadToEnd(); + } diff --git a/MauiAppStock/Resources/Splash/splash.svg b/MauiAppStock/Resources/Splash/splash.svg new file mode 100644 index 0000000..21dfb25 --- /dev/null +++ b/MauiAppStock/Resources/Splash/splash.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/MauiAppStock/Resources/Styles/Colors.xaml b/MauiAppStock/Resources/Styles/Colors.xaml new file mode 100644 index 0000000..30307a5 --- /dev/null +++ b/MauiAppStock/Resources/Styles/Colors.xaml @@ -0,0 +1,45 @@ + + + + + + + #512BD4 + #ac99ea + #242424 + #DFD8F7 + #9880e5 + #2B0B98 + + White + Black + #D600AA + #190649 + #1f1f1f + + #E1E1E1 + #C8C8C8 + #ACACAC + #919191 + #6E6E6E + #404040 + #212121 + #141414 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MauiAppStock/Resources/Styles/Styles.xaml b/MauiAppStock/Resources/Styles/Styles.xaml new file mode 100644 index 0000000..6641e3a --- /dev/null +++ b/MauiAppStock/Resources/Styles/Styles.xaml @@ -0,0 +1,427 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MauiAppStock/ViewModels/AppareilPiecesViewModel.cs b/MauiAppStock/ViewModels/AppareilPiecesViewModel.cs new file mode 100644 index 0000000..d3b8e96 --- /dev/null +++ b/MauiAppStock/ViewModels/AppareilPiecesViewModel.cs @@ -0,0 +1,119 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using MauiAppStock.Models; +using MauiAppStock.Data; +using MauiAppStock.Helpers; + +namespace MauiAppStock.ViewModels +{ + public class AppareilPiecesViewModel : BaseViewModel + { + private Appareil _appareil; + private List _allAssociations; + + public ObservableCollection AppareilPieces { get; set; } + public ICommand LoadAssociationsCommand { get; } + + private string _searchText; + public string SearchText + { + get => _searchText; + set + { + if (SetProperty(ref _searchText, value)) + { + ApplyFilterAndSort(); + } + } + } + + private bool _isAscending = true; + public bool IsAscending + { + get => _isAscending; + set + { + if (SetProperty(ref _isAscending, value)) + { + ApplyFilterAndSort(); + } + } + } + + public AppareilPiecesViewModel(Appareil appareil) + { + _appareil = appareil; + AppareilPieces = new ObservableCollection(); + _allAssociations = new List(); + LoadAssociationsCommand = new AsyncCommand(LoadAssociations); + } + + private async Task LoadAssociations() + { + _allAssociations = await Database.GetAppareilPiecesForAppareilAsync(_appareil.Id); + ApplyFilterAndSort(); + } + + private void ApplyFilterAndSort() + { + IEnumerable filtered = _allAssociations; + + // Filtrage par SearchText sur le nom de la pièce, en supprimant les diacritiques et en convertissant en minuscules. + if (!string.IsNullOrWhiteSpace(SearchText)) + { + string searchNormalized = RemoveDiacritics(SearchText).ToLowerInvariant(); + filtered = filtered.Where(a => + !string.IsNullOrEmpty(a.NomPiece) && + RemoveDiacritics(a.NomPiece).ToLowerInvariant().Contains(searchNormalized) + ); + } + + // Séparation des associations recommandées et non recommandées + var recommended = filtered.Where(a => a.EstRecommandee); + var nonRecommended = filtered.Where(a => !a.EstRecommandee); + + // Tri dans chaque groupe par ordre numérique (PieceId) puis alphabétique (NomPiece) + if (IsAscending) + { + recommended = recommended.OrderBy(a => a.PieceId).ThenBy(a => a.NomPiece); + nonRecommended = nonRecommended.OrderBy(a => a.PieceId).ThenBy(a => a.NomPiece); + } + else + { + recommended = recommended.OrderByDescending(a => a.PieceId).ThenByDescending(a => a.NomPiece); + nonRecommended = nonRecommended.OrderByDescending(a => a.PieceId).ThenByDescending(a => a.NomPiece); + } + + // Les associations recommandées apparaissent en premier. + var sorted = recommended.Concat(nonRecommended); + + AppareilPieces.Clear(); + foreach (var assoc in sorted) + { + AppareilPieces.Add(assoc); + } + } + + // Méthode pour supprimer les diacritiques (accents, cédilles, etc.) + private string RemoveDiacritics(string text) + { + if (string.IsNullOrWhiteSpace(text)) + return text; + + var normalizedString = text.Normalize(NormalizationForm.FormD); + var stringBuilder = new StringBuilder(); + + foreach (var c in normalizedString) + { + if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) + stringBuilder.Append(c); + } + return stringBuilder.ToString().Normalize(NormalizationForm.FormC); + } + } +} \ No newline at end of file diff --git a/MauiAppStock/ViewModels/AppareilsViewModel.cs b/MauiAppStock/ViewModels/AppareilsViewModel.cs new file mode 100644 index 0000000..780c7b4 --- /dev/null +++ b/MauiAppStock/ViewModels/AppareilsViewModel.cs @@ -0,0 +1,42 @@ +using System.Collections.ObjectModel; +using System.Threading.Tasks; +using System.Windows.Input; +using MauiAppStock.Models; +using MauiAppStock.Data; +using MauiAppStock.Helpers; + +namespace MauiAppStock.ViewModels +{ + public class AppareilsViewModel : BaseViewModel + { + public ObservableCollection Appareils { get; set; } + public ICommand LoadAppareilsCommand { get; } + public ICommand DeleteAppareilCommand { get; } + + public AppareilsViewModel() + { + Appareils = new ObservableCollection(); + LoadAppareilsCommand = new AsyncCommand(LoadAppareils); + DeleteAppareilCommand = new AsyncCommand(DeleteAppareil); + } + + private async Task LoadAppareils() + { + Appareils.Clear(); + var appareilsList = await Database.GetAppareilsAsync(); + foreach (var appareil in appareilsList) + { + Appareils.Add(appareil); + } + } + + private async Task DeleteAppareil(Appareil appareil) + { + if (appareil != null) + { + await Database.DeleteAppareilAsync(appareil); + Appareils.Remove(appareil); + } + } + } +} \ No newline at end of file diff --git a/MauiAppStock/ViewModels/BaseViewModel.cs b/MauiAppStock/ViewModels/BaseViewModel.cs new file mode 100644 index 0000000..90f6757 --- /dev/null +++ b/MauiAppStock/ViewModels/BaseViewModel.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace MauiAppStock.ViewModels +{ + public class BaseViewModel : INotifyPropertyChanged + { + bool isBusy; + public bool IsBusy + { + get => isBusy; + set => SetProperty(ref isBusy, value); + } + + protected bool SetProperty(ref T backingStore, T value, [CallerMemberName] string propertyName = "", System.Action onChanged = null) + { + if (EqualityComparer.Default.Equals(backingStore, value)) + return false; + + backingStore = value; + onChanged?.Invoke(); + OnPropertyChanged(propertyName); + return true; + } + + public event PropertyChangedEventHandler PropertyChanged; + protected void OnPropertyChanged([CallerMemberName] string propertyName = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} \ No newline at end of file diff --git a/MauiAppStock/ViewModels/PiecesViewModel.cs b/MauiAppStock/ViewModels/PiecesViewModel.cs new file mode 100644 index 0000000..738c36f --- /dev/null +++ b/MauiAppStock/ViewModels/PiecesViewModel.cs @@ -0,0 +1,31 @@ +using System.Collections.ObjectModel; +using System.Threading.Tasks; +using System.Windows.Input; +using MauiAppStock.Models; +using MauiAppStock.Data; +using MauiAppStock.Helpers; + +namespace MauiAppStock.ViewModels +{ + public class PiecesViewModel : BaseViewModel + { + public ObservableCollection Pieces { get; set; } + public ICommand LoadPiecesCommand { get; } + + public PiecesViewModel() + { + Pieces = new ObservableCollection(); + LoadPiecesCommand = new AsyncCommand(LoadPieces); + } + + private async Task LoadPieces() + { + Pieces.Clear(); + var piecesList = await Database.GetPiecesAsync(); + foreach (var piece in piecesList) + { + Pieces.Add(piece); + } + } + } +} \ No newline at end of file diff --git a/MauiAppStock/Views/AddAppareilPage.xaml b/MauiAppStock/Views/AddAppareilPage.xaml new file mode 100644 index 0000000..5af6b80 --- /dev/null +++ b/MauiAppStock/Views/AddAppareilPage.xaml @@ -0,0 +1,13 @@ + + + + +