|
@ -7,6 +7,7 @@ languages:
|
|||
- xaml
|
||||
products:
|
||||
- dotnet-maui
|
||||
- dotnet-core
|
||||
urlFragment: apps-pointofsale
|
||||
---
|
||||
|
||||
|
@ -20,6 +21,12 @@ This app demonstrates various techniques for building a desktop and mobile appli
|
|||
|
||||
![food-mobile-2](https://user-images.githubusercontent.com/41873/183740348-7f55d10d-8f79-4ee0-a71e-64b317cbd64f.png)
|
||||
|
||||
## Local Testing
|
||||
|
||||
If you want to test the full functionality of this app locally for iOS, make sure to rename the `Platforms/iOS/EntitlementsSample.plist` file to ``Platforms/iOS/Entitlements.plist`.
|
||||
|
||||
By doing so, you will need a matching provisioning profile in your Apple Developer accound in order for everything to work correctly.
|
||||
|
||||
### Credits
|
||||
|
||||
* Original design: https://www.uplabs.com/posts/foodos-food-point-of-sale
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(RunConfiguration)' == 'https' " />
|
||||
<PropertyGroup Condition=" '$(RunConfiguration)' == 'http' " />
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Datasync" Version="5.0.12" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Datasync.EFCore" Version="5.0.12" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Identity.Web" Version="2.0.7-preview" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Datasync;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.Identity.Web;
|
||||
//using TodoAppService.NET6.Db;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddMicrosoftIdentityWebApi(builder.Configuration);
|
||||
builder.Services.AddAuthorization();
|
||||
//var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
||||
|
||||
//if (connectionString == null)
|
||||
//{
|
||||
// throw new ApplicationException("DefaultConnection is not set");
|
||||
//}
|
||||
|
||||
//builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString));
|
||||
//builder.Services.AddDatasyncControllers();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Initialize the database
|
||||
//using (var scope = app.Services.CreateScope())
|
||||
//{
|
||||
// var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
// await context.InitializeDatabaseAsync().ConfigureAwait(false);
|
||||
//}
|
||||
|
||||
// Configure and run the web service.
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
//app.MapControllers();
|
||||
app.Run();
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:64228",
|
||||
"sslPort": 44388
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5128",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:7111;http://localhost:5128",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"AzureAD": {
|
||||
"Instance": "https://login.microsoftonline.com",
|
||||
"ClientId": "4c5a1b86-86f9-431a-a99d-999024e16848",
|
||||
"TenantId": "common"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"skuName": {
|
||||
"type": "string",
|
||||
"defaultValue": "F1",
|
||||
"allowedValues": [
|
||||
"F1",
|
||||
"D1",
|
||||
"B1",
|
||||
"B2",
|
||||
"B3",
|
||||
"S1",
|
||||
"S2",
|
||||
"S3",
|
||||
"P1",
|
||||
"P2",
|
||||
"P3",
|
||||
"P4"
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Describes plan's pricing tier and instance size. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/"
|
||||
}
|
||||
},
|
||||
"skuCapacity": {
|
||||
"type": "int",
|
||||
"defaultValue": 1,
|
||||
"maxValue": 3,
|
||||
"minValue": 1,
|
||||
"metadata": {
|
||||
"description": "Describes plan's instance count"
|
||||
}
|
||||
},
|
||||
"sqlAdministratorLogin": {
|
||||
"type": "string",
|
||||
"defaultValue": "appadmin",
|
||||
"metadata": {
|
||||
"description": "The admin user of the SQL Server"
|
||||
}
|
||||
},
|
||||
"sqlPassword": {
|
||||
"type": "secureString",
|
||||
"metadata": {
|
||||
"description": "The password of the admin user of the SQL Server"
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"type": "string",
|
||||
"defaultValue": "[resourceGroup().location]",
|
||||
"metadata": {
|
||||
"description": "Location for all resources."
|
||||
}
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"hostingPlanName": "[format('{0}hosting', uniqueString(resourceGroup().id))]",
|
||||
"websiteName": "[format('{0}-service', uniqueString(resourceGroup().id))]",
|
||||
"sqlserverName": "[format('{0}-dbserver', uniqueString(resourceGroup().id))]",
|
||||
"databaseName": "quickstart"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Sql/servers",
|
||||
"apiVersion": "2021-02-01-preview",
|
||||
"name": "[variables('sqlserverName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"properties": {
|
||||
"administratorLogin": "[parameters('sqlAdministratorLogin')]",
|
||||
"administratorLoginPassword": "[parameters('sqlPassword')]",
|
||||
"version": "12.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Sql/servers/databases",
|
||||
"apiVersion": "2021-02-01-preview",
|
||||
"name": "[format('{0}/{1}', variables('sqlserverName'), variables('databaseName'))]",
|
||||
"location": "[parameters('location')]",
|
||||
"sku": {
|
||||
"name": "Basic"
|
||||
},
|
||||
"properties": {
|
||||
"collation": "SQL_Latin1_General_CP1_CI_AS",
|
||||
"maxSizeBytes": 1073741824
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Sql/servers', variables('sqlserverName'))]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Sql/servers/firewallRules",
|
||||
"apiVersion": "2021-02-01-preview",
|
||||
"name": "[format('{0}/{1}', variables('sqlserverName'), 'AllowAllWindowsAzureIps')]",
|
||||
"properties": {
|
||||
"endIpAddress": "0.0.0.0",
|
||||
"startIpAddress": "0.0.0.0"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Sql/servers', variables('sqlserverName'))]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Web/serverfarms",
|
||||
"apiVersion": "2021-03-01",
|
||||
"name": "[variables('hostingPlanName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"tags": {
|
||||
"displayName": "HostingPlan"
|
||||
},
|
||||
"sku": {
|
||||
"name": "[parameters('skuName')]",
|
||||
"capacity": "[parameters('skuCapacity')]"
|
||||
},
|
||||
"properties": {
|
||||
"numberOfWorkers": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Web/sites",
|
||||
"apiVersion": "2021-03-01",
|
||||
"name": "[variables('websiteName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"tags": {
|
||||
"[format('hidden-related:{0}', resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName')))]": "empty",
|
||||
"displayName": "Website"
|
||||
},
|
||||
"properties": {
|
||||
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Web/sites/config",
|
||||
"apiVersion": "2021-03-01",
|
||||
"name": "[format('{0}/{1}', variables('websiteName'), 'connectionstrings')]",
|
||||
"properties": {
|
||||
"DefaultConnection": {
|
||||
"value": "[format('Data Source=tcp:{0},1433;Initial Catalog={1};User Id={2}@{3};Password={4};', reference(resourceId('Microsoft.Sql/servers', variables('sqlserverName'))).fullyQualifiedDomainName, variables('databaseName'), parameters('sqlAdministratorLogin'), reference(resourceId('Microsoft.Sql/servers', variables('sqlserverName'))).fullyQualifiedDomainName, parameters('sqlPassword'))]",
|
||||
"type": "SQLAzure"
|
||||
}
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Sql/servers', variables('sqlserverName'))]",
|
||||
"[resourceId('Microsoft.Web/sites', variables('websiteName'))]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": {
|
||||
"backendUrl": {
|
||||
"type": "string",
|
||||
"value": "[concat('https://', variables('websiteName'), '.azurewebsites.net')]"
|
||||
},
|
||||
"sqlUsername": {
|
||||
"type": "string",
|
||||
"value": "[parameters('sqlAdministratorLogin')]"
|
||||
},
|
||||
"sqlPassword": {
|
||||
"type": "string",
|
||||
"value": "[parameters('sqlPassword')]"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,8 @@ VisualStudioVersion = 17.0.31611.283
|
|||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PointOfSale", "PointOfSale\PointOfSale.csproj", "{88F24BAD-E7CD-4D00-87F4-702FE9AA7077}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PointOfSale.API", "PointOfSale.API\PointOfSale.API.csproj", "{E093156C-2134-4AE3-8C14-96CE94725BBF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -17,6 +19,10 @@ Global
|
|||
{88F24BAD-E7CD-4D00-87F4-702FE9AA7077}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{88F24BAD-E7CD-4D00-87F4-702FE9AA7077}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{88F24BAD-E7CD-4D00-87F4-702FE9AA7077}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{E093156C-2134-4AE3-8C14-96CE94725BBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E093156C-2134-4AE3-8C14-96CE94725BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E093156C-2134-4AE3-8C14-96CE94725BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E093156C-2134-4AE3-8C14-96CE94725BBF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug",
|
||||
"type": "comet",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "comet: Build"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:pages="clr-namespace:PointOfSale.Pages"
|
||||
xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
|
||||
xmlns:b="clr-namespace:PointOfSale.Common.Behaviors"
|
||||
xmlns:v="clr-namespace:PointOfSale.Pages.Views"
|
||||
x:Class="PointOfSale.AppShell"
|
||||
FlyoutWidth="104"
|
||||
|
@ -84,20 +85,18 @@
|
|||
Margin="0,15,0,15"/>
|
||||
|
||||
<RadioButton Value="home" IsChecked="True" Grid.Row="1"
|
||||
ToolTipProperties.Text="Home"
|
||||
b:CursorBehavior.AttachBehavior="True"
|
||||
CheckedChanged="OnMenuItemChanged">
|
||||
<RadioButton.Content>
|
||||
<Image Source="home.png">
|
||||
<!--<Image.Behaviors>
|
||||
<mct:IconTintColorBehavior
|
||||
TintColor="{Binding IsChecked,
|
||||
Source={RelativeSource AncestorType={x:Type RadioButton}, AncestorLevel=1,Mode=TemplatedParent},
|
||||
Converter={StaticResource CheckedColorConverter}}"/>
|
||||
</Image.Behaviors>-->
|
||||
|
||||
</Image>
|
||||
</RadioButton.Content>
|
||||
</RadioButton>
|
||||
|
||||
<RadioButton Value="dashboard" Grid.Row="2"
|
||||
ToolTipProperties.Text="Dashboard"
|
||||
CheckedChanged="OnMenuItemChanged">
|
||||
<RadioButton.Content>
|
||||
<Image Source="graph.png">
|
||||
|
@ -113,6 +112,7 @@
|
|||
</RadioButton>
|
||||
|
||||
<RadioButton Value="settings" Grid.Row="3"
|
||||
ToolTipProperties.Text="Settings"
|
||||
CheckedChanged="OnMenuItemChanged">
|
||||
<RadioButton.Content>
|
||||
<Image Source="setting.png">
|
||||
|
@ -128,6 +128,7 @@
|
|||
</RadioButton>
|
||||
|
||||
<RadioButton Value="discount" Grid.Row="4"
|
||||
ToolTipProperties.Text="Discount"
|
||||
CheckedChanged="OnMenuItemChanged">
|
||||
<RadioButton.Content>
|
||||
<Image Source="discount.png">
|
||||
|
@ -143,6 +144,7 @@
|
|||
</RadioButton>
|
||||
|
||||
<RadioButton Value="message" Grid.Row="5"
|
||||
ToolTipProperties.Text="Messages"
|
||||
CheckedChanged="OnMenuItemChanged">
|
||||
<RadioButton.Content>
|
||||
<Image Source="message.png">
|
||||
|
@ -158,13 +160,16 @@
|
|||
</RadioButton>
|
||||
|
||||
<RadioButton Value="notification" Grid.Row="6"
|
||||
ToolTipProperties.Text="Notifications"
|
||||
CheckedChanged="OnMenuItemChanged">
|
||||
<RadioButton.Content>
|
||||
<Image Source="notification.png" />
|
||||
</RadioButton.Content>
|
||||
</RadioButton>
|
||||
|
||||
<Image Source="logout.png" Margin="0,15,0,15" Grid.Row="7"/>
|
||||
<Image Source="logout.png"
|
||||
ToolTipProperties.Text="Logout"
|
||||
Margin="0,15,0,15" Grid.Row="7"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</Shell.FlyoutContentTemplate>
|
||||
|
|
|
@ -4,5 +4,7 @@
|
|||
xmlns:p="clr-namespace:PointOfSale.Pages.Handheld"
|
||||
x:Class="PointOfSale.AppShellMobile"
|
||||
Title="AppShellMobile">
|
||||
|
||||
<ShellContent ContentTemplate="{DataTemplate p:MobileLoginPage}" Route="login"/>
|
||||
<ShellContent ContentTemplate="{DataTemplate p:OrdersPage}" Route="orders"/>
|
||||
</Shell>
|
||||
|
|
|
@ -18,5 +18,6 @@ public partial class AppShellMobile : Shell
|
|||
Routing.RegisterRoute(nameof(PayPage), typeof(PayPage));
|
||||
Routing.RegisterRoute(nameof(SignaturePage), typeof(SignaturePage));
|
||||
Routing.RegisterRoute(nameof(ReceiptPage), typeof(ReceiptPage));
|
||||
Routing.RegisterRoute(nameof(ScanPage), typeof(ScanPage));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using CommunityToolkit.Maui.Behaviors;
|
||||
|
||||
namespace PointOfSale.Common.Behaviors;
|
||||
|
||||
public partial class CursorBehavior : PlatformBehavior<View>
|
||||
{
|
||||
public static readonly BindableProperty AttachBehaviorProperty =
|
||||
BindableProperty.CreateAttached("AttachBehavior", typeof(bool), typeof(CursorBehavior), false, propertyChanged: OnAttachBehaviorChanged);
|
||||
|
||||
public static bool GetAttachBehavior(BindableObject view)
|
||||
{
|
||||
return (bool)view.GetValue(AttachBehaviorProperty);
|
||||
}
|
||||
|
||||
public static void SetAttachBehavior(BindableObject view, bool value)
|
||||
{
|
||||
view.SetValue(AttachBehaviorProperty, value);
|
||||
}
|
||||
|
||||
static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
|
||||
{
|
||||
var btn = view as Button;
|
||||
if (btn == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool attachBehavior = (bool)newValue;
|
||||
if (attachBehavior)
|
||||
{
|
||||
btn.Behaviors.Add(new CursorBehavior());
|
||||
}
|
||||
else
|
||||
{
|
||||
var toRemove = btn.Behaviors.FirstOrDefault(b => b is CursorBehavior);
|
||||
if (toRemove != null)
|
||||
{
|
||||
btn.Behaviors.Remove(toRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
namespace PointOfSale.Data;
|
||||
|
||||
public static class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// The base URI for the Datasync service.
|
||||
/// </summary>
|
||||
public static string ServiceUri = "https://yojjaontbpmia-service.azurewebsites.net";
|
||||
|
||||
/// <summary>
|
||||
/// The application (client) ID for the native app within Azure Active Directory
|
||||
/// </summary>
|
||||
public static string ApplicationId = "e8b7e84c-1cb6-4619-bee9-ace98d4211e5";
|
||||
|
||||
/// <summary>
|
||||
/// The list of scopes to request
|
||||
/// </summary>
|
||||
public static string[] Scopes = new[]
|
||||
{
|
||||
"access_as_user"
|
||||
};
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
namespace PointOfSale.Data
|
||||
{
|
||||
public class UserAccount
|
||||
{
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
public string ID { get; set; }
|
||||
|
||||
public string UserPrincipalName { get; set; }
|
||||
|
||||
public UserAccount()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,11 @@
|
|||
using CommunityToolkit.Maui;
|
||||
using Microsoft.Maui.LifecycleEvents;
|
||||
using Microsoft.Maui.Platform;
|
||||
using MonkeyCache;
|
||||
using MonkeyCache.FileStore;
|
||||
using Plugin.Maui.KeyListener;
|
||||
using SkiaSharp.Views.Maui.Controls.Hosting;
|
||||
using ZXing.Net.Maui;
|
||||
|
||||
#if WINDOWS
|
||||
using Microsoft.UI;
|
||||
|
@ -22,14 +26,20 @@ public static class MauiProgram
|
|||
var builder = MauiApp.CreateBuilder();
|
||||
builder
|
||||
.UseMauiApp<App>()
|
||||
.UseBarcodeReader()
|
||||
.UseMauiCommunityToolkit()
|
||||
.UseSkiaSharp()
|
||||
.UseKeyListener()
|
||||
.ConfigureFonts(fonts =>
|
||||
{
|
||||
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
|
||||
fonts.AddFont("opensans_semibold.ttf", "OpenSansSemiBold");
|
||||
fonts.AddFont("fa_solid.ttf", "FontAwesome");
|
||||
fonts.AddFont("fabmdl2.ttf", "Fabric");
|
||||
})
|
||||
.ConfigureMauiHandlers(handlers =>
|
||||
{
|
||||
ModifyEntry();
|
||||
});
|
||||
|
||||
builder.Services.AddMauiBlazorWebView();
|
||||
|
@ -56,7 +66,7 @@ public static class MauiProgram
|
|||
});
|
||||
#endif
|
||||
|
||||
ModifyEntry();
|
||||
Barrel.ApplicationId = "com.simplyprofound.pointofsale";
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
|
@ -70,7 +80,9 @@ public static class MauiProgram
|
|||
#elif IOS || MACCATALYST
|
||||
handler.PlatformView.BorderStyle = UIKit.UITextBorderStyle.None;
|
||||
#elif WINDOWS
|
||||
// how can I remove the bottom border of the Entry?
|
||||
handler.PlatformView.FontWeight = Microsoft.UI.Text.FontWeights.Thin;
|
||||
handler.PlatformView.BorderThickness = new Microsoft.UI.Xaml.Thickness(0);
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
|
||||
namespace PointOfSale;
|
||||
|
||||
public class AddToOrderMessage : ValueChangedMessage<Item>
|
||||
{
|
||||
public AddToOrderMessage(Item product) : base(product)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
|
||||
namespace PointOfSale.Messages;
|
||||
|
||||
public class DragProductMessage : ValueChangedMessage<bool>
|
||||
{
|
||||
public DragProductMessage(bool value) : base(value)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ public static class AppData
|
|||
new Item(){ Title = "Hot Tea", Price = 4.00, Quantity = 1, Category = ItemCategory.Beverages, Image = "tea.png"},
|
||||
new Item(){ Title = "Coffee", Price = 4.00, Quantity = 1, Category = ItemCategory.Beverages, Image = "coffee.png"},
|
||||
new Item(){ Title = "Milk", Price = 5.00, Quantity = 1, Category = ItemCategory.Beverages, Image = "milk.png"},
|
||||
new Item(){ Title = "Juice", Price = 50.00, Quantity = 1, Category = ItemCategory.Beverages, Image = "juice.png"},
|
||||
};
|
||||
|
||||
public static List<Order> Orders { get; set; } = GenerateOrders();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
namespace PointOfSale.Models;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
public partial class Item
|
||||
public partial class Item : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
string title;
|
||||
|
|
|
@ -3,8 +3,7 @@ using PointOfSale.Pages.Handheld;
|
|||
|
||||
namespace PointOfSale.Models;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
public partial class Order
|
||||
public partial class Order : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private int table;
|
||||
|
@ -19,9 +18,9 @@ public partial class Order
|
|||
{
|
||||
get
|
||||
{
|
||||
var tot = items.Sum(i => (i.Price * i.Quantity));
|
||||
if (tip != 0)
|
||||
tot = tot + (tot * tip);
|
||||
var tot = Items.Sum(i => (i.Price * i.Quantity));
|
||||
if (Tip != 0)
|
||||
tot = tot + (tot * Tip);
|
||||
return tot.ToString("N2");
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +47,7 @@ public partial class Order
|
|||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async void Pay()
|
||||
private async Task Pay()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
namespace PointOfSale.Pages;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
public partial class DashboardViewModel
|
||||
public partial class DashboardViewModel : ObservableObject
|
||||
{
|
||||
[RelayCommand]
|
||||
async Task ViewAll()
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:handheld="clr-namespace:PointOfSale.Pages.Handheld"
|
||||
x:Class="PointOfSale.Pages.Handheld.MobileLoginPage"
|
||||
x:DataType="handheld:MobileLoginViewModel"
|
||||
Shell.NavBarIsVisible="false"
|
||||
Title="Login">
|
||||
|
||||
<ContentPage.BindingContext>
|
||||
<handheld:MobileLoginViewModel/>
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<Grid RowDefinitions="*,140,60,*" RowSpacing="20">
|
||||
|
||||
<Image Source="jajangmyeon.png" HorizontalOptions="Center"
|
||||
SemanticProperties.Description="Image of a bowl of noodles"
|
||||
Grid.Row="1"/>
|
||||
|
||||
<Button
|
||||
Text="Login"
|
||||
Command="{Binding LoginCommand}"
|
||||
MinimumWidthRequest="240"
|
||||
Grid.Row="2"
|
||||
SemanticProperties.Description="tap this button to login"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="Center" />
|
||||
</Grid>
|
||||
</ContentPage>
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
|
||||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
public partial class MobileLoginPage : ContentPage
|
||||
{
|
||||
public MobileLoginPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override async void OnNavigatedTo(NavigatedToEventArgs args)
|
||||
{
|
||||
base.OnNavigatedTo(args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
public partial class MobileLoginViewModel : ObservableObject
|
||||
{
|
||||
[RelayCommand]
|
||||
async Task Login()
|
||||
{
|
||||
await Shell.Current.GoToAsync("//orders");
|
||||
}
|
||||
|
||||
// display the message
|
||||
private async Task ShowMessage(string title, string message)
|
||||
{
|
||||
_ = App.Current.MainPage.Dispatcher.Dispatch(async () =>
|
||||
{
|
||||
await App.Current.MainPage.DisplayAlert(title, message, "OK").ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -11,14 +11,14 @@
|
|||
<handheld:OrderDetailsViewModel/>
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<Grid RowDefinitions="120, *, 66" Margin="20">
|
||||
<VerticalStackLayout VerticalOptions="Center" Spacing="8">
|
||||
<Grid RowDefinitions="Auto, 400, 66" Margin="20">
|
||||
<VerticalStackLayout VerticalOptions="Start" Spacing="8">
|
||||
<Label Text="Current Order" Style="{StaticResource LargeTitle}"/>
|
||||
<Label Text="{Binding Order.Table, StringFormat='TABLE {0}'}"/>
|
||||
<BoxView Style="{StaticResource HRule}"/>
|
||||
</VerticalStackLayout>
|
||||
|
||||
<CollectionView Grid.Row="1" ItemsSource="{Binding Order.Items}">
|
||||
<CollectionView Grid.Row="1" ItemsSource="{Binding Order.Items}" VerticalScrollBarVisibility="Never" Background="Transparent">
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:Item">
|
||||
<Grid ColumnDefinitions="160,60,*" ColumnSpacing="8" Margin="0,8" HeightRequest="70">
|
||||
|
@ -38,9 +38,8 @@
|
|||
</CollectionView.Header>
|
||||
</CollectionView>
|
||||
|
||||
<Grid ColumnSpacing="20" ColumnDefinitions="*,*" Grid.Row="2">
|
||||
<Button Text="Add" Grid.Column="0" Command="{Binding AddCommand}" Style="{StaticResource PrimaryButtonOutline}" HorizontalOptions="Fill"/>
|
||||
<Button Text="Pay" Grid.Column="1" Command="{Binding PayCommand}" HorizontalOptions="Fill"/>
|
||||
<Grid Grid.Row="2">
|
||||
<Button Text="Pay" Command="{Binding PayCommand}" HorizontalOptions="Fill"/>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
[QueryProperty("Order","Order")]
|
||||
[QueryProperty("Added", "Added")]
|
||||
public partial class OrderDetailsViewModel
|
||||
public partial class OrderDetailsViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
Order order;
|
||||
|
@ -18,7 +17,7 @@ public partial class OrderDetailsViewModel
|
|||
{
|
||||
var navigationParameter = new Dictionary<string, object>
|
||||
{
|
||||
{ "Order", order }
|
||||
{ "Order", Order }
|
||||
};
|
||||
await Shell.Current.GoToAsync($"{nameof(TipPage)}", navigationParameter);
|
||||
}
|
||||
|
@ -27,10 +26,4 @@ public partial class OrderDetailsViewModel
|
|||
Debug.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
async Task Add()
|
||||
{
|
||||
// await Shell.Current.GoToAsync($"{nameof(ScanPage)}");
|
||||
}
|
||||
}
|
|
@ -4,31 +4,110 @@
|
|||
xmlns:models="clr-namespace:PointOfSale.Models"
|
||||
xmlns:handheld="clr-namespace:PointOfSale.Pages.Handheld"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
|
||||
xmlns:ak="clr-namespace:AlohaKit.Animations;assembly=AlohaKit.Animations"
|
||||
x:Class="PointOfSale.Pages.Handheld.OrdersPage"
|
||||
Shell.NavBarIsVisible="False"
|
||||
x:DataType="handheld:OrdersViewModel"
|
||||
Title="OrdersPage">
|
||||
|
||||
<ContentPage.BindingContext>
|
||||
<handheld:OrdersViewModel/>
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<Grid RowDefinitions="120, *, 66" Margin="20">
|
||||
<VerticalStackLayout VerticalOptions="Center" Spacing="8">
|
||||
<Grid RowDefinitions="Auto, *, 66" Margin="20,20,20,0">
|
||||
<VerticalStackLayout VerticalOptions="Start" Spacing="4">
|
||||
<Label Text="Orders" Style="{StaticResource LargeTitle}"/>
|
||||
<Label Text="{Binding Source={x:Static system:DateTime.Today}, StringFormat=Date: {0:dddd, MMMM dd yyyy}, FallbackValue='Hello'}"/>
|
||||
<BoxView Style="{StaticResource HRule}"/>
|
||||
</VerticalStackLayout>
|
||||
|
||||
<CollectionView Grid.Row="1" Grid.RowSpan="2" ItemsSource="{Binding Orders}">
|
||||
<Grid Grid.Row="1"
|
||||
ColumnDefinitions="Auto"
|
||||
toolkit:StateContainer.CurrentState="{Binding PageCurrentState}">
|
||||
<toolkit:StateContainer.StateViews>
|
||||
<Grid ColumnDefinitions="80,100,*"
|
||||
RowDefinitions="40,*"
|
||||
Margin="0,8"
|
||||
ColumnSpacing="8"
|
||||
toolkit:StateView.StateKey="Loading">
|
||||
<Label Text="Table" Grid.Column="0" VerticalOptions="Center" FontAttributes="Bold"/>
|
||||
<Label Text="Total" Grid.Column="1" VerticalOptions="Center" FontAttributes="Bold"/>
|
||||
<Label Text="Status" Grid.Column="2" VerticalOptions="Center" HorizontalOptions="Start" FontAttributes="Bold"/>
|
||||
|
||||
<VerticalStackLayout Grid.Row="1" Grid.ColumnSpan="3" x:Name="ListPreview">
|
||||
<BindableLayout.ItemsSource>
|
||||
<x:Array Type="{x:Type x:String}">
|
||||
<x:String>one</x:String>
|
||||
<x:String>one</x:String>
|
||||
<x:String>one</x:String>
|
||||
<x:String>one</x:String>
|
||||
<x:String>one</x:String>
|
||||
<x:String>one</x:String>
|
||||
<x:String>one</x:String>
|
||||
<x:String>one</x:String>
|
||||
</x:Array>
|
||||
</BindableLayout.ItemsSource>
|
||||
<BindableLayout.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid ColumnDefinitions="80,100,*" ColumnSpacing="8" Margin="0,8" HeightRequest="70">
|
||||
<Border Stroke="Transparent" StrokeThickness="1" VerticalOptions="Center" HorizontalOptions="Start"
|
||||
HeightRequest="60" WidthRequest="60" Background="{StaticResource NeutralLighter}">
|
||||
<Border.StrokeShape>
|
||||
<Ellipse Frame="0,0,60,60" />
|
||||
</Border.StrokeShape>
|
||||
<Grid>
|
||||
<BoxView HeightRequest="30" HorizontalOptions="Fill" VerticalOptions="Center" Color="{StaticResource NeutralLighter}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<BoxView HeightRequest="30" Grid.Column="1" HorizontalOptions="Fill" VerticalOptions="Center" Color="{StaticResource NeutralLighter}"/>
|
||||
<BoxView HeightRequest="30" Grid.Column="2" HorizontalOptions="Fill" VerticalOptions="Center" Color="{StaticResource NeutralLighter}"/>
|
||||
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
</BindableLayout.ItemTemplate>
|
||||
|
||||
<VerticalStackLayout.Resources>
|
||||
<ak:StoryBoard x:Key="LoadingBoard" Target="{x:Reference ListPreview}">
|
||||
<ak:FadeToAnimation Opacity="0.5" Duration="500"/>
|
||||
<ak:FadeToAnimation Opacity="1" Duration="500"/>
|
||||
<ak:FadeToAnimation Opacity="0.5" Duration="500"/>
|
||||
<ak:FadeToAnimation Opacity="1" Duration="500"/>
|
||||
<ak:FadeToAnimation Opacity="0.5" Duration="500"/>
|
||||
<ak:FadeToAnimation Opacity="1" Duration="500"/>
|
||||
</ak:StoryBoard>
|
||||
</VerticalStackLayout.Resources>
|
||||
|
||||
<VerticalStackLayout.Triggers>
|
||||
<DataTrigger
|
||||
TargetType="VerticalStackLayout"
|
||||
Binding="{Binding PageCurrentState}"
|
||||
Value="Loading">
|
||||
<DataTrigger.EnterActions>
|
||||
<ak:BeginAnimation
|
||||
Animation="{StaticResource LoadingBoard}" />
|
||||
</DataTrigger.EnterActions>
|
||||
</DataTrigger>
|
||||
</VerticalStackLayout.Triggers>
|
||||
</VerticalStackLayout>
|
||||
</Grid>
|
||||
|
||||
<CollectionView ItemsSource="{Binding Orders}"
|
||||
VerticalOptions="Start"
|
||||
HeightRequest="600"
|
||||
VerticalScrollBarVisibility="Never"
|
||||
toolkit:StateView.StateKey="Loaded">
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:Order">
|
||||
<Grid ColumnDefinitions="80,100,*" ColumnSpacing="8" Margin="0,8" HeightRequest="70" >
|
||||
<Grid.GestureRecognizers>
|
||||
<TapGestureRecognizer Command="{Binding PayCommand}"/>
|
||||
</Grid.GestureRecognizers>
|
||||
|
||||
<Border Stroke="Transparent" StrokeThickness="1" VerticalOptions="Center" HorizontalOptions="Start"
|
||||
HeightRequest="60" WidthRequest="60" Background="{x:Static models:Order.RandomBrush}"
|
||||
>
|
||||
HeightRequest="60" WidthRequest="60" Background="{x:Static models:Order.RandomBrush}">
|
||||
<Border.StrokeShape>
|
||||
<Ellipse Frame="0,0,60,60" />
|
||||
</Border.StrokeShape>
|
||||
|
@ -49,12 +128,24 @@
|
|||
<Label Text="Status" Grid.Column="2" VerticalOptions="Center" HorizontalOptions="Start" FontAttributes="Bold"/>
|
||||
</Grid>
|
||||
</CollectionView.Header>
|
||||
<CollectionView.Footer>
|
||||
<Grid HeightRequest="66" ColumnSpacing="8">
|
||||
<!-- buffer for the content to flow behind but above the tabs-->
|
||||
</Grid>
|
||||
</CollectionView.Footer>
|
||||
</CollectionView>
|
||||
</toolkit:StateContainer.StateViews>
|
||||
</Grid>
|
||||
|
||||
<FlexLayout Grid.Row="2" AlignContent="SpaceAround" JustifyContent="SpaceAround"
|
||||
<FlexLayout Grid.Row="2"
|
||||
AlignContent="SpaceAround"
|
||||
JustifyContent="SpaceAround"
|
||||
Background="{StaticResource DarkBg1Transparent}">
|
||||
<Image Source="home.png"/>
|
||||
<Image Source="logout.png"/>
|
||||
<ImageButton Source="logout.png"
|
||||
Command="{Binding LogOutCommand}"
|
||||
/>
|
||||
|
||||
</FlexLayout>
|
||||
|
||||
</Grid>
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
|
||||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
public partial class OrdersPage : ContentPage
|
||||
{
|
||||
|
|
|
@ -1,13 +1,47 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
public partial class OrdersViewModel
|
||||
public partial class OrdersViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<Order> _orders;
|
||||
|
||||
[ObservableProperty]
|
||||
private string displayName;
|
||||
|
||||
[ObservableProperty]
|
||||
private string displayEmail;
|
||||
|
||||
[ObservableProperty]
|
||||
private ImageSource profilePhoto;
|
||||
|
||||
[ObservableProperty]
|
||||
private string pageCurrentState = "Loading";
|
||||
|
||||
[RelayCommand]
|
||||
public async Task LogOut()
|
||||
{
|
||||
var result = await App.Current.MainPage.DisplayAlert("", "Do you want to logout?", "Yes", "Ooops, no");
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
await Shell.Current.GoToAsync("//login");
|
||||
}
|
||||
|
||||
public OrdersViewModel()
|
||||
{
|
||||
_orders = new ObservableCollection<Order>(AppData.Orders);
|
||||
DelayedLoad().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
private async Task DelayedLoad()
|
||||
{
|
||||
await Task.Delay(4000);
|
||||
PageCurrentState = "Loaded";
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
<handheld:PayViewModel/>
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<Grid RowDefinitions="120,*"
|
||||
<Grid RowDefinitions="Auto,*"
|
||||
RowSpacing="20"
|
||||
Margin="20"
|
||||
RadioButtonGroup.GroupName="PaymentMethod"
|
||||
|
@ -21,7 +21,7 @@
|
|||
<Grid.GestureRecognizers>
|
||||
<TapGestureRecognizer Command="{Binding PayCommand}"/>
|
||||
</Grid.GestureRecognizers>
|
||||
<VerticalStackLayout VerticalOptions="Center" Spacing="8" Grid.ColumnSpan="2">
|
||||
<VerticalStackLayout VerticalOptions="Start" Spacing="8" Grid.ColumnSpan="2">
|
||||
<Label Text="Insert, Tap, Swipe" Style="{StaticResource LargeTitle}"/>
|
||||
<BoxView Style="{StaticResource HRule}"/>
|
||||
</VerticalStackLayout>
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
[QueryProperty("Order","Order")]
|
||||
public partial class PayViewModel
|
||||
public partial class PayViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
Order order;
|
||||
|
||||
[RelayCommand]
|
||||
async void Pay()
|
||||
async Task Pay()
|
||||
{
|
||||
var navigationParameter = new Dictionary<string, object>
|
||||
{
|
||||
{ "Order", order }
|
||||
{ "Order", Order }
|
||||
};
|
||||
await Shell.Current.GoToAsync($"{nameof(SignaturePage)}", navigationParameter);
|
||||
}
|
||||
|
|
4
8.0/Apps/PointOfSale/src/PointOfSale/Pages/Handheld/ReceiptPage.xaml
Normal file → Executable file
|
@ -22,14 +22,14 @@
|
|||
|
||||
</ContentPage.Resources>
|
||||
|
||||
<Grid RowDefinitions="120,180,40,120,120,*,66"
|
||||
<Grid RowDefinitions="Auto,180,40,120,120,*,66"
|
||||
RowSpacing="20"
|
||||
ColumnDefinitions="*,*"
|
||||
ColumnSpacing="20"
|
||||
Margin="20"
|
||||
RadioButtonGroup.GroupName="ReceiptOption"
|
||||
>
|
||||
<VerticalStackLayout VerticalOptions="Center" Spacing="8" Grid.ColumnSpan="2">
|
||||
<VerticalStackLayout VerticalOptions="Start" Spacing="8" Grid.ColumnSpan="2">
|
||||
<Label Text="Payment Successful" Style="{StaticResource LargeTitle}"/>
|
||||
<Label Text="{Binding Order.Total, StringFormat='Your Bill: ${0}'}"/>
|
||||
<BoxView Style="{StaticResource HRule}"/>
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
[QueryProperty("Order","Order")]
|
||||
public partial class ReceiptViewModel
|
||||
public partial class ReceiptViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
Order order;
|
||||
|
||||
[RelayCommand]
|
||||
async void Done()
|
||||
async Task Done()
|
||||
{
|
||||
await Shell.Current.GoToAsync("///orders");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:z="clr-namespace:ZXing.Net.Maui.Controls;assembly=ZXing.Net.MAUI"
|
||||
xmlns:a="clr-namespace:PointOfSale"
|
||||
xmlns:i="clr-namespace:Icons"
|
||||
x:Class="PointOfSale.Pages.Handheld.ScanPage"
|
||||
Shell.PresentationMode="ModalAnimated"
|
||||
Title="Scan">
|
||||
<Grid>
|
||||
<z:CameraBarcodeReaderView
|
||||
Grid.Row="0" Grid.RowSpan="3"
|
||||
x:Name="barcodeView"
|
||||
BarcodesDetected="BarcodesDetected"
|
||||
/>
|
||||
|
||||
<Border WidthRequest="240" HeightRequest="240"
|
||||
VerticalOptions="Center" HorizontalOptions="Center"
|
||||
Stroke="White"
|
||||
StrokeThickness="3">
|
||||
<Border.StrokeShape>
|
||||
<RoundRectangle CornerRadius="12"/>
|
||||
</Border.StrokeShape>
|
||||
</Border>
|
||||
|
||||
<ImageButton
|
||||
HeightRequest="60" WidthRequest="60"
|
||||
VerticalOptions="Start" HorizontalOptions="Start"
|
||||
Clicked="ImageButton_Clicked"
|
||||
Aspect="Center"
|
||||
Source="{FontImage FontFamily=Fabric, Color=White, Glyph={x:Static i:FabIconFont.Back},Size=18}"/>
|
||||
|
||||
<!--<Grid
|
||||
Grid.Row="3"
|
||||
BackgroundColor="#aa000000"
|
||||
Padding="20"
|
||||
ColumnDefinitions="Auto,*,Auto">
|
||||
|
||||
<Button Text="🔄️" Grid.Column="0" BackgroundColor="#aa000000" CornerRadius="8" BorderColor="Black" Clicked="SwitchCameraButton_Clicked" />
|
||||
|
||||
<z:BarcodeGeneratorView
|
||||
x:Name="barcodeGenerator"
|
||||
Grid.Column="1"
|
||||
HorizontalOptions="Center"
|
||||
VerticalOptions="Center"
|
||||
HeightRequest="100"
|
||||
WidthRequest="100"
|
||||
ForegroundColor="DarkBlue"
|
||||
Format="QrCode"
|
||||
Value="Bla"
|
||||
BarcodeMargin="1" />
|
||||
|
||||
<Button Text="💡" Grid.Column="2" BackgroundColor="#aa000000" CornerRadius="8" BorderColor="Black" Clicked="TorchButton_Clicked" />
|
||||
</Grid>-->
|
||||
</Grid>
|
||||
</ContentPage>
|
|
@ -0,0 +1,52 @@
|
|||
using PointOfSale.Models;
|
||||
using ZXing.Net.Maui;
|
||||
|
||||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
public partial class ScanPage : ContentPage
|
||||
{
|
||||
public ScanPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
barcodeView.Options = new BarcodeReaderOptions
|
||||
{
|
||||
Formats = BarcodeFormats.All,
|
||||
AutoRotate = true,
|
||||
Multiple = true
|
||||
};
|
||||
}
|
||||
|
||||
protected void BarcodesDetected(object sender, BarcodeDetectionEventArgs e)
|
||||
{
|
||||
foreach (var barcode in e.Results)
|
||||
Console.WriteLine($"Barcodes: {barcode.Format} -> {barcode.Value}");
|
||||
|
||||
Dispatcher.DispatchAsync(async () =>
|
||||
{
|
||||
var r = e.Results.First();
|
||||
|
||||
await CloseModal(r.Value);
|
||||
});
|
||||
}
|
||||
|
||||
private async Task CloseModal(string value)
|
||||
{
|
||||
var item = new Item
|
||||
{
|
||||
Price = 0,
|
||||
Quantity = 1,
|
||||
Title = value
|
||||
};
|
||||
var navigationParameter = new Dictionary<string, object>
|
||||
{
|
||||
{ "Item", item }
|
||||
};
|
||||
|
||||
await Shell.Current.GoToAsync("..", navigationParameter);
|
||||
}
|
||||
|
||||
async void ImageButton_Clicked(System.Object sender, System.EventArgs e)
|
||||
{
|
||||
await Shell.Current.GoToAsync("..");
|
||||
}
|
||||
}
|
4
8.0/Apps/PointOfSale/src/PointOfSale/Pages/Handheld/SignaturePage.xaml
Normal file → Executable file
|
@ -10,11 +10,11 @@
|
|||
<handheld:SignatureViewModel/>
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<Grid RowDefinitions="120,180,60,*,66"
|
||||
<Grid RowDefinitions="Auto,180,60,*,66"
|
||||
RowSpacing="20"
|
||||
Margin="20">
|
||||
|
||||
<VerticalStackLayout VerticalOptions="Center" Spacing="8">
|
||||
<VerticalStackLayout VerticalOptions="Start" Spacing="8">
|
||||
<Label Text="Add Signature" Style="{StaticResource LargeTitle}"/>
|
||||
<BoxView Style="{StaticResource HRule}"/>
|
||||
</VerticalStackLayout>
|
||||
|
|
|
@ -3,9 +3,8 @@ using PointOfSale.Messages;
|
|||
|
||||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
[QueryProperty("Order","Order")]
|
||||
public partial class SignatureViewModel
|
||||
public partial class SignatureViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
Order order;
|
||||
|
@ -14,21 +13,23 @@ public partial class SignatureViewModel
|
|||
async Task Done()
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<SaveSignatureMessage>(
|
||||
new SaveSignatureMessage(order.Table)
|
||||
new SaveSignatureMessage(Order.Table)
|
||||
);
|
||||
|
||||
var navigationParameter = new Dictionary<string, object>
|
||||
{
|
||||
{ "Order", order }
|
||||
{ "Order", Order }
|
||||
};
|
||||
await Shell.Current.GoToAsync($"{nameof(ReceiptPage)}", navigationParameter);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
void Clear()
|
||||
Task Clear()
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<ClearSignatureMessage>(
|
||||
new ClearSignatureMessage(true)
|
||||
); ;
|
||||
);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
</Style>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<Grid RowDefinitions="120,160,160,160,*,66"
|
||||
<Grid RowDefinitions="Auto,160,160,160,*,66"
|
||||
RowSpacing="20"
|
||||
ColumnDefinitions="*,*"
|
||||
ColumnSpacing="20"
|
||||
|
@ -27,7 +27,7 @@
|
|||
RadioButtonGroup.GroupName="TipAmount"
|
||||
RadioButtonGroup.SelectedValue="{Binding Tip}"
|
||||
>
|
||||
<VerticalStackLayout VerticalOptions="Center" Spacing="8" Grid.ColumnSpan="2">
|
||||
<VerticalStackLayout VerticalOptions="Start" Spacing="8" Grid.ColumnSpan="2">
|
||||
<Label Text="Add a Tip" Style="{StaticResource LargeTitle}"/>
|
||||
<Label Text="{Binding Order.Total, StringFormat='Your Bill: ${0}'}"/>
|
||||
<BoxView Style="{StaticResource HRule}"/>
|
||||
|
@ -113,6 +113,7 @@
|
|||
</RadioButton.Content>
|
||||
</RadioButton>
|
||||
|
||||
<Button Grid.Row="5" HorizontalOptions="Fill" Grid.ColumnSpan="2" Text="Continue" Command="{Binding ContinueCommand}"/>
|
||||
<Button Grid.Row="5" HorizontalOptions="Fill" Grid.Column="0" Text="Add Coupon" Command="{Binding AddCommand}" Style="{StaticResource SecondaryButtonOutline}"/>
|
||||
<Button Grid.Row="5" HorizontalOptions="Fill" Grid.Column="1" Text="Continue" Command="{Binding ContinueCommand}"/>
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
namespace PointOfSale.Pages.Handheld;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
[QueryProperty("Order","Order")]
|
||||
public partial class TipViewModel
|
||||
public partial class TipViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
Order order;
|
||||
|
@ -12,17 +11,23 @@ public partial class TipViewModel
|
|||
|
||||
partial void OnTipChanged(double value)
|
||||
{
|
||||
order.Tip = value;
|
||||
Order.Tip = value;
|
||||
OnPropertyChanged(nameof(Order));
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
async void Continue()
|
||||
async Task Continue()
|
||||
{
|
||||
var navigationParameter = new Dictionary<string, object>
|
||||
{
|
||||
{ "Order", order }
|
||||
{ "Order", Order }
|
||||
};
|
||||
await Shell.Current.GoToAsync($"{nameof(PayPage)}", navigationParameter);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
async Task Add()
|
||||
{
|
||||
await Shell.Current.GoToAsync($"{nameof(ScanPage)}");
|
||||
}
|
||||
}
|
|
@ -6,11 +6,12 @@
|
|||
xmlns:pages="clr-namespace:PointOfSale.Pages"
|
||||
xmlns:m="clr-namespace:PointOfSale.Models"
|
||||
xmlns:l="clr-namespace:CustomLayouts"
|
||||
xmlns:b="clr-namespace:PointOfSale.Common.Behaviors"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||
x:DataType="pages:HomeViewModel"
|
||||
x:Class="PointOfSale.Pages.HomePage"
|
||||
Shell.NavBarIsVisible="False"
|
||||
Title="HomePage">
|
||||
Shell.NavBarIsVisible="{OnPlatform False, WinUI=True}"
|
||||
Title="">
|
||||
|
||||
<ContentPage.BindingContext>
|
||||
<pages:HomeViewModel/>
|
||||
|
@ -19,24 +20,35 @@
|
|||
<ContentPage.MenuBarItems>
|
||||
<MenuBarItem Text="File">
|
||||
<MenuFlyoutItem Text="Preferences"
|
||||
ParentChanged="MenuFlyoutItem_ParentChanged"
|
||||
Command="{Binding PreferencesCommand}" />
|
||||
</MenuBarItem>
|
||||
<MenuBarItem Text="Products">
|
||||
<MenuFlyoutItem Text="Add Product" Command="{Binding AddProductCommand}"
|
||||
ParentChanged="MenuFlyoutItem_ParentChanged"/>
|
||||
<MenuFlyoutItem Text="Add Product Category"/>
|
||||
<MenuFlyoutItem Text="Add Product"
|
||||
Command="{Binding AddProductCommand}">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="A" Modifiers="Cmd,Shift"/>
|
||||
<KeyboardAccelerator Key="A" Modifiers="Ctrl"/>
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
<MenuFlyoutItem.IconImageSource>
|
||||
<FontImageSource Glyph=""
|
||||
Size="12"
|
||||
Color="Black"
|
||||
FontFamily="Fabric" />
|
||||
</MenuFlyoutItem.IconImageSource>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Text="Add Product Category"
|
||||
IconImageSource="{FontImage , FontFamily=Fabric, Color=Black, Size=12}"
|
||||
/>
|
||||
</MenuBarItem>
|
||||
</ContentPage.MenuBarItems>
|
||||
|
||||
|
||||
<Grid RowDefinitions="100,70,*"
|
||||
ColumnDefinitions="*,400"
|
||||
Margin="24,24,0,0"
|
||||
<Grid RowDefinitions="100,Auto,*"
|
||||
RowSpacing="10"
|
||||
ColumnDefinitions="{OnPlatform '*,400', WinUI='*,440'}"
|
||||
Margin="24,0,0,0"
|
||||
x:Name="PageGrid">
|
||||
|
||||
|
||||
|
||||
<ScrollView Grid.Row="2">
|
||||
<Grid RowDefinitions="70,*">
|
||||
<Label Text="Choose Dishes" Style="{StaticResource Title1}"/>
|
||||
|
@ -47,34 +59,72 @@
|
|||
<BindableLayout.ItemTemplate>
|
||||
<DataTemplate x:DataType="m:Item">
|
||||
<Grid RowDefinitions="30,230" WidthRequest="200">
|
||||
<Grid.Behaviors>
|
||||
<b:CursorBehavior/>
|
||||
</Grid.Behaviors>
|
||||
<Grid.GestureRecognizers>
|
||||
<DragGestureRecognizer
|
||||
DragStarting="OnDragStarting"
|
||||
DropCompleted="OnDropCompleted"
|
||||
/>
|
||||
</Grid.GestureRecognizers>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="DefaultStates">
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter
|
||||
TargetName="CardBg"
|
||||
Property="Border.Background"
|
||||
Value="{StaticResource Primary}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Normal">
|
||||
<VisualState.Setters>
|
||||
<Setter
|
||||
TargetName="CardBg"
|
||||
Property="Border.Background"
|
||||
Value="{StaticResource DarkBg2Brush}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<FlyoutBase.ContextFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem Text="Edit Details"
|
||||
CommandParameter="docs" />
|
||||
<MenuFlyoutItem Text="Remove"
|
||||
CommandParameter="eng" />
|
||||
</MenuFlyout>
|
||||
</FlyoutBase.ContextFlyout>
|
||||
<Border Background="{StaticResource DarkBg2Brush}"
|
||||
Stroke="{StaticResource DarkBg2Brush}"
|
||||
StrokeThickness="1"
|
||||
Grid.Row="1"
|
||||
x:Name="CardBg"
|
||||
>
|
||||
<Border.StrokeShape>
|
||||
<RoundRectangle CornerRadius="16"/>
|
||||
</Border.StrokeShape>
|
||||
|
||||
|
||||
</Border>
|
||||
<VerticalStackLayout Grid.RowSpan="2" Margin="20,0,20,20"
|
||||
<VerticalStackLayout Grid.RowSpan="2" Margin="20,0,20,10"
|
||||
VerticalOptions="End"
|
||||
Spacing="6">
|
||||
|
||||
<Label Text="{Binding Title}" HorizontalOptions="Center" Style="{StaticResource Title2}" HorizontalTextAlignment="Center"/>
|
||||
<Label Text="{Binding Price, StringFormat='${0}'}" HorizontalOptions="Center"/>
|
||||
<!--<Label Text="20 Bowls available" HorizontalOptions="Center" Style="{StaticResource Subhead}"/>-->
|
||||
<Label Text="{Binding Price, StringFormat='{0:C}'}" HorizontalOptions="Center"/>
|
||||
</VerticalStackLayout>
|
||||
<Image
|
||||
Grid.RowSpan="2" VerticalOptions="Start"
|
||||
Source="{Binding Image, FallbackValue=food_01.png}" HorizontalOptions="Center"/>
|
||||
Margin="0,-20,0,0"
|
||||
Source="{Binding Image, FallbackValue=food_01.png}"
|
||||
HorizontalOptions="Center"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</BindableLayout.ItemTemplate>
|
||||
</l:HorizontalWrapLayout>
|
||||
|
||||
|
||||
</Grid>
|
||||
|
||||
</ScrollView>
|
||||
|
@ -117,14 +167,13 @@
|
|||
<!-- Tab Control -->
|
||||
<Grid Grid.Row="1">
|
||||
<BoxView Style="{StaticResource HRule}"
|
||||
Margin="0,31,0,0"
|
||||
VerticalOptions="Start"
|
||||
Margin="0,0,0,0"
|
||||
VerticalOptions="End"
|
||||
/>
|
||||
<HorizontalStackLayout Spacing="20"
|
||||
RadioButtonGroup.GroupName="MenuCategories"
|
||||
RadioButtonGroup.SelectedValue="{Binding Category}"
|
||||
|
||||
>
|
||||
VerticalOptions="End">
|
||||
<BindableLayout.ItemsSource>
|
||||
<x:Array Type="{x:Type x:String}">
|
||||
<x:String>Noodles</x:String>
|
||||
|
@ -140,6 +189,9 @@
|
|||
<RadioButton.ControlTemplate>
|
||||
<ControlTemplate>
|
||||
<Grid RowDefinitions="30,4">
|
||||
<Grid.Behaviors>
|
||||
<b:CursorBehavior/>
|
||||
</Grid.Behaviors>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CheckedStates">
|
||||
|
@ -168,6 +220,32 @@
|
|||
Value="Transparent"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<!-- <VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter
|
||||
TargetName="TextLabel"
|
||||
Property="Label.TextColor"
|
||||
Value="{StaticResource Primary}"/>
|
||||
<Setter
|
||||
TargetName="Indicator"
|
||||
Property="BoxView.Color"
|
||||
Value="{StaticResource Primary}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Normal">
|
||||
<VisualState.Setters>
|
||||
<Setter
|
||||
TargetName="TextLabel"
|
||||
Property="Label.TextColor"
|
||||
Value="White"/>
|
||||
<Setter
|
||||
TargetName="Indicator"
|
||||
Property="BoxView.Color"
|
||||
Value="Transparent"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState> -->
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
|
@ -181,11 +259,26 @@
|
|||
</DataTemplate>
|
||||
</BindableLayout.ItemTemplate>
|
||||
</HorizontalStackLayout>
|
||||
|
||||
|
||||
</Grid>
|
||||
|
||||
<v:OrderCartView Grid.Column="1" Grid.RowSpan="3"/>
|
||||
<BoxView Color="Black"
|
||||
Opacity="0"
|
||||
Grid.RowSpan="3" Grid.ColumnSpan="2"
|
||||
HorizontalOptions="Fill"
|
||||
VerticalOptions="Fill"
|
||||
Margin="-24"
|
||||
InputTransparent="True"
|
||||
x:Name="BlockScreen"
|
||||
/>
|
||||
|
||||
<v:OrderCartView Grid.Column="1" Grid.RowSpan="3">
|
||||
<v:OrderCartView.GestureRecognizers>
|
||||
<DropGestureRecognizer
|
||||
DragOver="OnDragOver"
|
||||
Drop="OnDrop"/>
|
||||
</v:OrderCartView.GestureRecognizers>
|
||||
</v:OrderCartView>
|
||||
|
||||
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
|
||||
|
||||
using Microsoft.Maui.Controls.Platform;
|
||||
using Microsoft.Maui.Platform;
|
||||
using PointOfSale.Messages;
|
||||
#if IOS || MACCATALYST
|
||||
using UIKit;
|
||||
#endif
|
||||
|
||||
namespace PointOfSale.Pages;
|
||||
|
||||
public partial class HomePage : ContentPage
|
||||
{
|
||||
|
||||
|
||||
public HomePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigatedToEventArgs args)
|
||||
{
|
||||
base.OnNavigatedTo(args);
|
||||
|
||||
WeakReferenceMessenger.Default.Register<AddProductMessage>(this, (r, m) =>
|
||||
{
|
||||
|
@ -26,7 +34,7 @@ public partial class HomePage : ContentPage
|
|||
|
||||
|
||||
|
||||
public void NavSubContent(bool show)
|
||||
public async void NavSubContent(bool show)
|
||||
{
|
||||
var displayWidth = DeviceDisplay.Current.MainDisplayInfo.Width;
|
||||
|
||||
|
@ -37,7 +45,11 @@ public partial class HomePage : ContentPage
|
|||
Grid.SetRowSpan(addForm, 3);
|
||||
// translate off screen right
|
||||
addForm.TranslationX = displayWidth - addForm.X;
|
||||
addForm.TranslateTo(0, 0, 800, easing: Easing.CubicOut);
|
||||
_ = addForm.TranslateTo(0, 0, 800, easing: Easing.CubicOut);
|
||||
|
||||
_ = BlockScreen.FadeTo(0.8, 800, easing: Easing.CubicOut);
|
||||
BlockScreen.InputTransparent = false;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -46,11 +58,91 @@ public partial class HomePage : ContentPage
|
|||
var view = (AddProductView)PageGrid.Children.Where(v => v.GetType() == typeof(AddProductView)).SingleOrDefault();
|
||||
|
||||
var x = DeviceDisplay.Current.MainDisplayInfo.Width;
|
||||
view.TranslateTo(displayWidth - view.X, 0, 800, easing: Easing.CubicIn);
|
||||
_ = view.TranslateTo(displayWidth - view.X, 0, 800, easing: Easing.CubicIn);
|
||||
|
||||
if (view != null)
|
||||
_ = BlockScreen.FadeTo(0, 800, easing: Easing.CubicOut);
|
||||
BlockScreen.InputTransparent = true;
|
||||
|
||||
await Task.Delay(800);
|
||||
if (view != null){
|
||||
PageGrid.Children.Remove(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void OnDragStarting(object sender, DragStartingEventArgs e)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<DragProductMessage>(new DragProductMessage(true));
|
||||
|
||||
Item item = (Item)(sender as Element).Parent.BindingContext;
|
||||
e.Data.Properties.Add("Product", item);
|
||||
|
||||
var previewImage = string.Empty;
|
||||
if(item.Title == "Soda") {
|
||||
previewImage = "hunter.png";
|
||||
} else if(item.Title == "Hot Tea") {
|
||||
previewImage = "maddy.png";
|
||||
} else if(item.Title == "Milk") {
|
||||
previewImage = "sweeky.png";
|
||||
} else if(item.Title == "Coffee") {
|
||||
previewImage = "david.png";
|
||||
} else if(item.Title == "Iced Tea") {
|
||||
previewImage = "beth.png";
|
||||
} else if(item.Title == "Juice") {
|
||||
previewImage = "rachel.png";
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
#if IOS || MACCATALYST
|
||||
Func<UIKit.UIDragPreview> action = () =>
|
||||
{
|
||||
var image = UIImage.FromBundle(previewImage);
|
||||
UIKit.UIImageView imageView = new UIKit.UIImageView(image);
|
||||
imageView.ContentMode = UIKit.UIViewContentMode.Center;
|
||||
imageView.Frame = new CoreGraphics.CGRect(0, 0, 250, 250);
|
||||
return new UIKit.UIDragPreview(imageView);
|
||||
};
|
||||
|
||||
e.PlatformArgs.SetPreviewProvider(action);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnDragOver(object sender, DragEventArgs e)
|
||||
{
|
||||
#if IOS || MACCATALYST
|
||||
e.PlatformArgs.SetDropProposal(new UIKit.UIDropProposal(UIKit.UIDropOperation.Copy));
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnDropCompleted(object sender, DropCompletedEventArgs e)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<DragProductMessage>(new DragProductMessage(false));
|
||||
}
|
||||
|
||||
void OnDrop(object sender, DropEventArgs e)
|
||||
{
|
||||
Item product = (Item)e.Data.Properties["Product"];
|
||||
Debug.WriteLine($"{product.Title}");
|
||||
WeakReferenceMessenger.Default.Send<AddToOrderMessage>(new AddToOrderMessage(product));
|
||||
// Perform logic to take action based on retrieved value.
|
||||
}
|
||||
|
||||
IDispatcherTimer timer;
|
||||
|
||||
void OnPointerPressed(object sender, PointerEventArgs e)
|
||||
{
|
||||
timer = Dispatcher.CreateTimer();
|
||||
timer.Interval = TimeSpan.FromMilliseconds(2000);
|
||||
timer.Tick += (s, e) =>
|
||||
{
|
||||
timer.Stop();
|
||||
WeakReferenceMessenger.Default.Send<AddProductMessage>(new AddProductMessage(true));
|
||||
};
|
||||
}
|
||||
|
||||
void OnPointerReleased(object sender, PointerEventArgs e)
|
||||
{
|
||||
timer.Stop();
|
||||
}
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
using System;
|
||||
using PointOfSale.Messages;
|
||||
|
||||
namespace PointOfSale.Pages;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
public partial class HomeViewModel
|
||||
public partial class HomeViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
ObservableCollection<Item> _products;
|
||||
|
@ -10,10 +11,10 @@ public partial class HomeViewModel
|
|||
[ObservableProperty]
|
||||
string category = ItemCategory.Noodles.ToString();
|
||||
|
||||
partial void OnCategoryChanged(string cat)
|
||||
partial void OnCategoryChanged(string value)
|
||||
{
|
||||
ItemCategory category = (ItemCategory)Enum.Parse(typeof(ItemCategory), cat);
|
||||
_products = new ObservableCollection<Item>(
|
||||
ItemCategory category = (ItemCategory)Enum.Parse(typeof(ItemCategory), value);
|
||||
Products = new ObservableCollection<Item>(
|
||||
AppData.Items.Where(x => x.Category == category).ToList()
|
||||
);
|
||||
OnPropertyChanged(nameof(Products));
|
||||
|
@ -21,7 +22,7 @@ public partial class HomeViewModel
|
|||
|
||||
public HomeViewModel()
|
||||
{
|
||||
_products = new ObservableCollection<Item>(
|
||||
Products = new ObservableCollection<Item>(
|
||||
AppData.Items.Where(x=>x.Category == ItemCategory.Noodles).ToList()
|
||||
);
|
||||
}
|
||||
|
@ -33,8 +34,8 @@ public partial class HomeViewModel
|
|||
}
|
||||
|
||||
[RelayCommand]
|
||||
async Task AddProduct()
|
||||
void AddProduct()
|
||||
{
|
||||
MessagingCenter.Send<HomeViewModel, string>(this, "action", "add");
|
||||
WeakReferenceMessenger.Default.Send<AddProductMessage>(new AddProductMessage(true));
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
namespace PointOfSale.Pages;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
public partial class SettingsViewModel
|
||||
public partial class SettingsViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
ObservableCollection<Item> _products;
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
</Style>
|
||||
</ContentView.Resources>
|
||||
|
||||
<Grid RowDefinitions="*,108">
|
||||
<ScrollView>
|
||||
<Grid RowDefinitions="*,108" ColumnDefinitions="*,*" ColumnSpacing="0">
|
||||
<ScrollView Grid.ColumnSpan="2">
|
||||
<VerticalStackLayout Spacing="20" Margin="24">
|
||||
<Label Text="Add a Product" Style="{StaticResource Title1}" />
|
||||
<BoxView Style="{StaticResource HRule}"/>
|
||||
|
@ -96,7 +96,14 @@
|
|||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
|
||||
<Button Text="Save" Grid.Row="1" Margin="24" Command="{Binding SaveCommand}"
|
||||
<Button Text="Cancel"
|
||||
Grid.Row="1" Grid.Column="0"
|
||||
Margin="24,24,12,24"
|
||||
Style="{StaticResource SecondaryButtonOutline}"
|
||||
HorizontalOptions="Fill"
|
||||
Command="{Binding CancelCommand}" />
|
||||
|
||||
<Button Text="Save" Grid.Row="1" Grid.Column="1" Margin="12,24,24,24" Command="{Binding SaveCommand}"
|
||||
HorizontalOptions="Fill"
|
||||
/>
|
||||
</Grid>
|
||||
|
|
|
@ -1,9 +1,32 @@
|
|||
namespace PointOfSale.Pages;
|
||||
using System.Security.Cryptography;
|
||||
using Plugin.Maui.KeyListener;
|
||||
using PointOfSale.Messages;
|
||||
|
||||
public partial class AddProductView
|
||||
namespace PointOfSale.Pages;
|
||||
|
||||
public partial class AddProductView : ContentView, IDisposable
|
||||
{
|
||||
KeyboardBehavior kb = new KeyboardBehavior();
|
||||
public AddProductView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.Behaviors.Add(kb);
|
||||
|
||||
kb.KeyUp += Kb_KeyUp;
|
||||
}
|
||||
|
||||
private void Kb_KeyUp(object sender, KeyPressedEventArgs e)
|
||||
{
|
||||
if(e.Keys == KeyboardKeys.Escape)
|
||||
{
|
||||
(this.BindingContext as AddProductViewModel).CancelCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
kb.KeyUp -= Kb_KeyUp;
|
||||
this.Behaviors.Remove(kb);
|
||||
}
|
||||
}
|
||||
|
|
24
8.0/Apps/PointOfSale/src/PointOfSale/Pages/Views/AddProductViewModel.cs
Normal file → Executable file
|
@ -1,8 +1,9 @@
|
|||
using System;
|
||||
using PointOfSale.Messages;
|
||||
|
||||
namespace PointOfSale.Pages;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
public partial class AddProductViewModel
|
||||
public partial class AddProductViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
Item item = new Item();
|
||||
|
@ -17,13 +18,21 @@ public partial class AddProductViewModel
|
|||
ImageSource image;
|
||||
|
||||
[RelayCommand]
|
||||
async void Save()
|
||||
void Save()
|
||||
{
|
||||
ItemCategory cat = (ItemCategory)Enum.Parse(typeof(ItemCategory), category);
|
||||
item.Category = cat;
|
||||
AppData.Items.Add(item);
|
||||
ItemCategory cat = (ItemCategory)Enum.Parse(typeof(ItemCategory), Category);
|
||||
Item.Category = cat;
|
||||
AppData.Items.Add(Item);
|
||||
|
||||
MessagingCenter.Send<AddProductViewModel, string>(this, "action", "done");
|
||||
WeakReferenceMessenger.Default.Send<AddProductMessage>(new AddProductMessage(false));
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
Task Cancel()
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<AddProductMessage>(new AddProductMessage(false));
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
|
@ -58,6 +67,7 @@ public partial class AddProductViewModel
|
|||
catch (Exception ex)
|
||||
{
|
||||
// The user canceled or something went wrong
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -12,19 +12,66 @@
|
|||
<views:OrderCartViewModel/>
|
||||
</ContentView.BindingContext>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="DefaultStates">
|
||||
<VisualState x:Name="AcceptDrop">
|
||||
<VisualState.Setters>
|
||||
<Setter
|
||||
Property="Background"
|
||||
Value="{StaticResource Primary}"/>
|
||||
<Setter
|
||||
TargetName="PlaceOrderButton"
|
||||
Property="Button.IsEnabled"
|
||||
Value="False"/>
|
||||
<Setter
|
||||
TargetName="OrderTypes"
|
||||
Property="HorizontalStackLayout.IsVisible"
|
||||
Value="False"/>
|
||||
<Setter
|
||||
TargetName="AddItemIcon"
|
||||
Property="Image.IsVisible"
|
||||
Value="True"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Normal">
|
||||
<VisualState.Setters>
|
||||
<Setter
|
||||
Property="Background"
|
||||
Value="{StaticResource DarkBg2Brush}"/>
|
||||
<Setter
|
||||
TargetName="PlaceOrderButton"
|
||||
Property="Button.IsEnabled"
|
||||
Value="True"/>
|
||||
<Setter
|
||||
TargetName="OrderTypes"
|
||||
Property="HorizontalStackLayout.IsVisible"
|
||||
Value="True"/>
|
||||
<Setter
|
||||
TargetName="AddItemIcon"
|
||||
Property="Image.IsVisible"
|
||||
Value="False"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
|
||||
|
||||
<Grid RowDefinitions="*,108">
|
||||
<ScrollView>
|
||||
<VerticalStackLayout Margin="24" Spacing="20">
|
||||
<Label
|
||||
Text="Order #4773"
|
||||
Style="{StaticResource Title1}" />
|
||||
<HorizontalStackLayout Spacing="12">
|
||||
<HorizontalStackLayout Spacing="12"
|
||||
x:Name="OrderTypes">
|
||||
<HorizontalStackLayout.Resources>
|
||||
|
||||
<Style TargetType="RadioButton">
|
||||
<Setter Property="ControlTemplate" Value="{StaticResource ButtonRadioTemplate}"/>
|
||||
</Style>
|
||||
<Setter Property="HorizontalOptions" Value="Start"/>
|
||||
|
||||
</Style>
|
||||
</HorizontalStackLayout.Resources>
|
||||
<RadioButton Content="Dine In" IsChecked="True"/>
|
||||
<RadioButton Content="Carry Out"/>
|
||||
|
@ -39,7 +86,7 @@
|
|||
<BoxView Style="{StaticResource HRule}"/>
|
||||
|
||||
<VerticalStackLayout Spacing="12"
|
||||
BindableLayout.ItemsSource="{Binding Order.Items}">
|
||||
BindableLayout.ItemsSource="{Binding Items}">
|
||||
<BindableLayout.ItemTemplate>
|
||||
<DataTemplate x:DataType="m:Item">
|
||||
<Grid ColumnDefinitions="60*,20*,20*">
|
||||
|
@ -53,7 +100,7 @@
|
|||
<FormattedString>
|
||||
<Span Text="{Binding Title}"/>
|
||||
<Span Text="{x:Static system:Environment.NewLine}"/>
|
||||
<Span TextColor="{StaticResource TextSecondary}" FontSize="12" Text="{Binding Price, StringFormat='${0}'}"/>
|
||||
<Span TextColor="{StaticResource TextSecondary}" FontSize="12" Text="{Binding Price, StringFormat='{0:C}'}"/>
|
||||
</FormattedString>
|
||||
</Label.FormattedText>
|
||||
</Label>
|
||||
|
@ -61,8 +108,9 @@
|
|||
|
||||
<Border
|
||||
Grid.Column="1"
|
||||
HorizontalOptions="Start"
|
||||
HeightRequest="44"
|
||||
WidthRequest="44"
|
||||
WidthRequest="46"
|
||||
Background="{StaticResource DarkBg1Brush}"
|
||||
Stroke="{StaticResource SecondaryBrush}"
|
||||
StrokeThickness="1">
|
||||
|
@ -92,8 +140,17 @@
|
|||
</VerticalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
<Button Text="Place Order" HorizontalOptions="Fill" Margin="24" Grid.Row="1"
|
||||
<Button Text="Place Order"
|
||||
x:Name="PlaceOrderButton"
|
||||
HorizontalOptions="Fill" Margin="24" Grid.Row="1"
|
||||
Command="{Binding PlaceOrderCommand}"/>
|
||||
<Image x:Name="AddItemIcon"
|
||||
Source="{FontImage , FontFamily=Fabric, Size=48}"
|
||||
Aspect="AspectFit"
|
||||
HorizontalOptions="Center"
|
||||
VerticalOptions="End"
|
||||
Margin="0,-100,0,0"
|
||||
Grid.Row="0"/>
|
||||
|
||||
</Grid>
|
||||
</ContentView>
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
namespace PointOfSale.Pages.Views;
|
||||
using PointOfSale.Messages;
|
||||
|
||||
namespace PointOfSale.Pages.Views;
|
||||
|
||||
public partial class OrderCartView : ContentView
|
||||
{
|
||||
public OrderCartView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
WeakReferenceMessenger.Default.Register<DragProductMessage>(this, (r, m) =>
|
||||
{
|
||||
if(m.Value)
|
||||
VisualStateManager.GoToState(this, "AcceptDrop");
|
||||
else
|
||||
VisualStateManager.GoToState(this, "Normal");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,51 @@
|
|||
using System;
|
||||
namespace PointOfSale.Pages.Views;
|
||||
|
||||
[INotifyPropertyChanged]
|
||||
public partial class OrderCartViewModel
|
||||
public partial class OrderCartViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
Order order;
|
||||
|
||||
[ObservableProperty]
|
||||
ObservableCollection<Item> items;
|
||||
|
||||
int index = 0;
|
||||
|
||||
public OrderCartViewModel()
|
||||
{
|
||||
Order = AppData.Orders.First();
|
||||
Items = new ObservableCollection<Item>(Order.Items);
|
||||
|
||||
WeakReferenceMessenger.Default.Register<AddToOrderMessage>(this, (r, m) =>
|
||||
{
|
||||
AddToOrder(m.Value);
|
||||
Items = new ObservableCollection<Item>(Order.Items);
|
||||
OnPropertyChanged(nameof(Items));
|
||||
});
|
||||
}
|
||||
|
||||
private void AddToOrder(Item item)
|
||||
{
|
||||
//if item is in the order alread, increment the quantity
|
||||
var existing = Order.Items.Where(x => x.Title == item.Title).SingleOrDefault();
|
||||
if (existing != null)
|
||||
{
|
||||
existing.Quantity++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Order.Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
async Task PlaceOrder()
|
||||
{
|
||||
await App.Current.MainPage.DisplayAlert("Not Implemented", "Wouldn't it be cool tho?", "Okay");
|
||||
if(index < (AppData.Orders.Count - 1))
|
||||
index++;
|
||||
else
|
||||
index = 0;
|
||||
Order = AppData.Orders[index];
|
||||
}
|
||||
}
|
|
@ -1,6 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="net.dot.pointofsale" android:versionCode="1" android:versionName="1.0.0">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
|
||||
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true" android:label="Food">
|
||||
<activity android:name="microsoft.identity.client.BrowserTabActivity" android:configChanges="orientation|screenSize" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="msale8b7e84c-1cb6-4619-bee9-ace98d4211e5" android:host="auth" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="MauiAppBasic.Platforms.Android.Resources.MsalActivity" android:configChanges="orientation|screenSize" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="msale8b7e84c-1cb6-4619-bee9-ace98d4211e5" android:host="auth" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
|
@ -1,10 +1,17 @@
|
|||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using PointOfSale.Data;
|
||||
|
||||
namespace PointOfSale;
|
||||
|
||||
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
|
||||
public class MainActivity : MauiAppCompatActivity
|
||||
{
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Foundation;
|
||||
using UIKit;
|
||||
|
||||
namespace PointOfSale;
|
||||
|
||||
|
@ -6,4 +7,14 @@ namespace PointOfSale;
|
|||
public class AppDelegate : MauiUIApplicationDelegate
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
|
||||
public override void BuildMenu(IUIMenuBuilder builder)
|
||||
{
|
||||
base.BuildMenu(builder);
|
||||
var formatMenuIdentifier = UIMenuIdentifier.Format.GetConstant();
|
||||
builder.RemoveMenu(formatMenuIdentifier);
|
||||
|
||||
var editIdentifier = UIMenuIdentifier.Edit.GetConstant();
|
||||
builder.RemoveMenu(editIdentifier);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using AppKit;
|
||||
using UIKit;
|
||||
|
||||
namespace PointOfSale.Common.Behaviors;
|
||||
|
||||
public partial class CursorBehavior
|
||||
{
|
||||
UIHoverGestureRecognizer _hoverRecognizer;
|
||||
|
||||
protected override void OnAttachedTo(View bindable, UIView platformView)
|
||||
{
|
||||
_hoverRecognizer = new UIHoverGestureRecognizer(HandlerHoverDetection);
|
||||
platformView.AddGestureRecognizer(_hoverRecognizer);
|
||||
base.OnAttachedTo(bindable, platformView);
|
||||
}
|
||||
|
||||
protected override void OnDetachedFrom(View bindable, UIView platformView)
|
||||
{
|
||||
platformView.RemoveGestureRecognizer(_hoverRecognizer);
|
||||
_hoverRecognizer.Dispose();
|
||||
_hoverRecognizer = null;
|
||||
base.OnDetachedFrom(bindable, platformView);
|
||||
}
|
||||
|
||||
void HandlerHoverDetection(UIHoverGestureRecognizer args)
|
||||
{
|
||||
if (args.State == UIGestureRecognizerState.Began ||
|
||||
args.State == UIGestureRecognizerState.Changed)
|
||||
{
|
||||
NSCursor.PointingHandCursor.Set();
|
||||
}
|
||||
else if (args.State == UIGestureRecognizerState.Ended)
|
||||
{
|
||||
NSCursor.ArrowCursor.Set();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,9 +7,8 @@
|
|||
IgnorableNamespaces="uap rescap">
|
||||
|
||||
<Identity
|
||||
Name="8D1C6CD3-CA27-4254-B76F-15B91335C418"
|
||||
Publisher="CN=User Name"
|
||||
Version="1.0.0.0" />
|
||||
Version="1.0.0.0" Name="a045a695-05e1-4353-a3d0-5cd58ec52a45"/>
|
||||
|
||||
<Properties>
|
||||
<DisplayName>PointOfSale</DisplayName>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Rename this file to Entitlements.plist for the full functionality to work. However, this will require you to have a matching provisioning profile in your Apple Developer Account. -->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)com.microsoft.adalcache</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -30,5 +30,7 @@
|
|||
<string>Assets.xcassets/appicon.appiconset</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Barcode Scanning</string>
|
||||
<key>UIRequiresPersistentWiFi</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -16,13 +16,12 @@
|
|||
<UseMaui>true</UseMaui>
|
||||
<SingleProject>true</SingleProject>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
|
||||
<!-- Display name -->
|
||||
<ApplicationTitle>Food</ApplicationTitle>
|
||||
<ApplicationTitle>Point of Sale</ApplicationTitle>
|
||||
|
||||
<!-- App Identifier -->
|
||||
<ApplicationId>net.dot.pointofsale</ApplicationId>
|
||||
<ApplicationId>com.simplyprofound.pointofsale</ApplicationId>
|
||||
|
||||
<!-- Versions -->
|
||||
<ApplicationVersion>1</ApplicationVersion>
|
||||
|
@ -40,18 +39,6 @@
|
|||
<AssemblyName>Food</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-ios|AnyCPU'">
|
||||
<CodesignProvision>dPOSDev</CodesignProvision>
|
||||
<CodesignKey>Apple Development: Created via API (2NJFZDD9ZM)</CodesignKey>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0-ios|AnyCPU'">
|
||||
<CodesignProvision>Automatic</CodesignProvision>
|
||||
<CodesignKey>iPhone Developer</CodesignKey>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- App Icon -->
|
||||
<MauiIcon Include="Resources\appicon.svg" ForegroundFile="Resources\appiconfg.svg" Color="#252836" />
|
||||
|
@ -76,11 +63,22 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Maui" Version="6.0.0" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageReference Include="Microcharts.Maui" Version="1.0.0" />
|
||||
<PackageReference Include="SkiaSharp.Extended.UI.Maui" Version="2.0.0-preview.86" />
|
||||
<PackageReference Include="CommunityToolkit.Maui" Version="3.0.0" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||
<PackageReference Include="Microcharts" Version="0.9.5.9" />
|
||||
<PackageReference Include="Redth.ZXing.Net.Maui" Version="0.1.0-preview.4" />
|
||||
<PackageReference Include="SkiaSharp.Extended.UI.Maui" Version="2.0.0-preview.92" />
|
||||
<PackageReference Include="Ril.BlazorSignatureCanvas" Version="0.1.0-alpha" />
|
||||
<PackageReference Include="Microsoft.Identity.Client" Version="4.48.1" />
|
||||
<PackageReference Include="MonkeyCache" Version="2.0.0-beta" />
|
||||
<PackageReference Include="MonkeyCache.FileStore" Version="2.0.0-beta" />
|
||||
<PackageReference Include="AlohaKit.Animations" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
||||
<PackageReference Include="AsyncAwaitBestPractices" Version="6.0.6" />
|
||||
<PackageReference Include="Plugin.Maui.KeyListener" Version="1.0.0-preview1" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="$(MauiVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
После Ширина: | Высота: | Размер: 72 KiB |
После Ширина: | Высота: | Размер: 70 KiB |
После Ширина: | Высота: | Размер: 58 KiB |
После Ширина: | Высота: | Размер: 15 KiB |
После Ширина: | Высота: | Размер: 72 KiB |
После Ширина: | Высота: | Размер: 44 KiB |
После Ширина: | Высота: | Размер: 87 KiB |
|
@ -85,6 +85,7 @@
|
|||
</VisualStateManager.VisualStateGroups>
|
||||
<Label Text="{TemplateBinding Content}"
|
||||
Margin="12,7"
|
||||
HorizontalTextAlignment="{OnPlatform Start, WinUI=Center}"
|
||||
x:Name="TextLabel" />
|
||||
</Border>
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
.my-special-styling-class {
|
||||
background-color: #0a58ca;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
|