Compare commits

...

10 Commits

Author SHA1 Message Date
e7357bd78a Implemetato databese locale con EntityFramework 2026-02-17 17:40:33 +01:00
544c9e8237 Gestiti allegati da galleria e fotocamera e aggiunto sentry 2026-02-17 10:23:46 +01:00
c1a133c61e Aggiunti nuovi campi al form 2026-02-17 09:47:14 +01:00
69f2dee309 Iniziata implementazione form rilevazione 2026-02-13 17:28:48 +01:00
06cc41ef8b Aggiunte chiamate api per dati utili 2026-02-12 12:59:46 +01:00
5afe4f4745 Aggiunta selezione negozio 2026-02-12 10:43:16 +01:00
d8bef12f30 Creata pagina "user" 2026-02-06 18:08:40 +01:00
755f78ef9d Gestito login 2026-02-06 10:04:36 +01:00
ecafebae7f Prima configurazione e struttura 2026-02-04 17:31:00 +01:00
1a949051ca Rinominati file progetto 2026-02-04 12:14:03 +01:00
212 changed files with 4844 additions and 1479 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
# Specific to the EFCore-Blazor sample app # Specific to the EFCore-Blazor sample app
*.db *.db
*.db3
*.db-shm *.db-shm
*.db-wal *.db-wal

15
.idea/.idea.SteUp/.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,15 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/modules.xml
/projectSettingsUpdater.xml
/.idea.SteUp.iml
/contentModel.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

1
.idea/.idea.SteUp/.idea/.name generated Normal file
View File

@@ -0,0 +1 @@
SteUp

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="RiderAndroidProjectSystem" />
</component>
</project>

12
.idea/.idea.SteUp/.idea/dataSources.xml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="design-time" uuid="3ba1249b-165e-400b-a102-6ea88e0757ff">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/SteUp.Data/design-time.db3</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="SteUp.Maui">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

4
.idea/.idea.SteUp/.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

8
.idea/.idea.SteUp/.idea/indexLayout.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.annotation.annotation">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.annotation/1.6.0.4/jar/androidx.annotation.annotation.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.annotation.annotation-jvm">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.annotation.jvm/1.6.0.2/jar/androidx.annotation.annotation-jvm.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.arch.core.core-common">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.arch.core.common/2.2.0.3/jar/androidx.arch.core.core-common.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.collection.collection">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.collection/1.2.0.9/jar/androidx.collection.collection.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.collection.collection-jvm">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.collection.jvm/1.5.0.1/jar/androidx.collection.collection-jvm.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.collection.collection-ktx">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.collection.ktx/1.2.0.9/jar/androidx.collection.collection-ktx.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.concurrent.concurrent-futures">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.concurrent.futures/1.1.0.14/jar/androidx.concurrent.concurrent-futures.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.constraintlayout.constraintlayout-core">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.constraintlayout.core/1.0.4.6/jar/androidx.constraintlayout.constraintlayout-core.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.lifecycle.lifecycle-common">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.lifecycle.common/2.6.1.3/jar/androidx.lifecycle.lifecycle-common.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.lifecycle.lifecycle-common-java8">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.lifecycle.common.java8/2.8.7.2/jar/androidx.lifecycle.lifecycle-common-java8.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.lifecycle.lifecycle-common-jvm">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.lifecycle.common.jvm/2.8.7.3/jar/androidx.lifecycle.lifecycle-common-jvm.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="androidx.resourceinspection.resourceinspection-annotation">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.androidx.resourceinspection.annotation/1.0.1.7/jar/androidx.resourceinspection.resourceinspection-annotation.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="annotations">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.android.glide.annotations/4.15.1.2/jar/annotations.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="disklrucache">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.android.glide.disklrucache/4.15.1.2/jar/disklrucache.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="guava-listenablefuture">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.google.guava.listenablefuture/1.0.0.14/jar/guava-listenablefuture.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="org.jetbrains.annotations-24.0.1">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.jetbrains.annotations/24.0.1.3/jar/org.jetbrains.annotations-24.0.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="org.jetbrains.kotlin.kotlin-stdlib-1.9.0">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.kotlin.stdlib/1.9.0.1/jar/org.jetbrains.kotlin.kotlin-stdlib-1.9.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="org.jetbrains.kotlin.kotlin-stdlib-common-1.9.0">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.kotlin.stdlib.common/1.9.0.1/jar/org.jetbrains.kotlin.kotlin-stdlib-common-1.9.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="org.jetbrains.kotlin.kotlin-stdlib-jdk7-1.9.0">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.kotlin.stdlib.jdk7/1.9.0.1/jar/org.jetbrains.kotlin.kotlin-stdlib-jdk7-1.9.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="org.jetbrains.kotlin.kotlin-stdlib-jdk7-2.0.0">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.kotlin.stdlib.jdk7/2.0.0/jar/org.jetbrains.kotlin.kotlin-stdlib-jdk7-2.0.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="org.jetbrains.kotlin.kotlin-stdlib-jdk8-1.9.0">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.kotlin.stdlib.jdk8/1.9.0.1/jar/org.jetbrains.kotlin.kotlin-stdlib-jdk8-1.9.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="org.jetbrains.kotlin.kotlin-stdlib-jdk8-2.0.0">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.kotlin.stdlib.jdk8/2.0.0/jar/org.jetbrains.kotlin.kotlin-stdlib-jdk8-2.0.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="org.jetbrains.kotlinx.kotlinx-coroutines-android-1.7.2">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.kotlinx.coroutines.android/1.7.2.1/jar/org.jetbrains.kotlinx.kotlinx-coroutines-android-1.7.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm-1.7.2">
<CLASSES>
<root url="jar://$USER_HOME$/.nuget/packages/xamarin.kotlinx.coroutines.core.jvm/1.7.2.1/jar/org.jetbrains.kotlinx.kotlinx-coroutines-core-jvm-1.7.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

7
.idea/.idea.SteUp/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using SteUp.Shared.Core.Entities;
namespace SteUp.Data.LocalDb;
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
{
public DbSet<Ispezione> Ispezioni => Set<Ispezione>();
public DbSet<Scheda> Schede => Set<Scheda>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Ispezione>()
.HasKey(x => new { x.CodMdep, x.Data, x.Rilevatore });
modelBuilder.Entity<Scheda>()
.HasOne(x => x.Ispezione)
.WithMany(x => x.Schede)
.HasForeignKey(x => new { x.CodMdep, x.Data, x.Rilevatore })
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Scheda>()
.HasIndex(x => new { x.CodMdep, x.Data, x.Rilevatore });
}
}

View File

@@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
namespace SteUp.Data.LocalDb;
public class AppDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlite("Data Source=design-time.db3")
.Options;
return new AppDbContext(options);
}
}

View File

@@ -0,0 +1,12 @@
using Microsoft.EntityFrameworkCore;
using SteUp.Shared.Core.Interface.LocalDb;
namespace SteUp.Data.LocalDb;
public class DbInitializer(AppDbContext db) : IDbInitializer
{
public async Task InitializeAsync()
{
await db.Database.MigrateAsync();
}
}

View File

@@ -0,0 +1,17 @@
using Microsoft.Maui.Storage;
namespace SteUp.Data.LocalDb;
public interface IDbPathProvider
{
string GetDbPath();
}
public class DbPathProvider : IDbPathProvider
{
private const string DbName = "steup_db.db3";
public string GetDbPath() =>
Path.Combine(FileSystem.AppDataDirectory, DbName);
}

View File

@@ -0,0 +1,127 @@
using Microsoft.EntityFrameworkCore;
using SteUp.Shared.Core.Entities;
using SteUp.Shared.Core.Interface.LocalDb;
namespace SteUp.Data.LocalDb.EntityServices;
public class IspezioniService(AppDbContext db) : IIspezioniService
{
public Task<Ispezione?> GetIspezioneAsync(string codMdep, DateOnly data, string rilevatore) =>
db.Ispezioni
.Include(x => x.Schede)
.FirstOrDefaultAsync(x =>
x.CodMdep == codMdep &&
x.Data == data &&
x.Rilevatore == rilevatore);
public Task<List<Ispezione>> GetAllIspezioniWithSchedeAsync() =>
db.Ispezioni
.Include(x => x.Schede)
.AsNoTracking()
.OrderByDescending(x => x.Data)
.ToListAsync();
public async Task AddIspezioneAsync(Ispezione ispezione)
{
db.Ispezioni.Add(ispezione);
await db.SaveChangesAsync();
}
public async Task<Ispezione> GetOrCreateIspezioneAsync(string codMdep, DateOnly data, string rilevatore)
{
var existing = await db.Ispezioni
.Include(x => x.Schede)
.FirstOrDefaultAsync(x =>
x.CodMdep == codMdep &&
x.Data == data &&
x.Rilevatore == rilevatore);
if (existing != null)
return existing;
var created = new Ispezione
{
CodMdep = codMdep,
Data = data,
Rilevatore = rilevatore
};
db.Ispezioni.Add(created);
await db.SaveChangesAsync();
return created;
}
/// <summary>
/// Cancella l'ispezione e tutte le schede collegate.
/// </summary>
public async Task<bool> DeleteIspezioneAsync(string codMdep, DateOnly data, string rilevatore)
{
var ispezione = await db.Ispezioni
.FirstOrDefaultAsync(x =>
x.CodMdep == codMdep &&
x.Data == data &&
x.Rilevatore == rilevatore);
if (ispezione is null)
return false;
db.Ispezioni.Remove(ispezione);
await db.SaveChangesAsync();
return true;
}
public async Task AddSchedaAsync(string codMdep, DateOnly data, string rilevatore, Scheda scheda)
{
// assicura che il parent esista
await GetOrCreateIspezioneAsync(codMdep, data, rilevatore);
scheda.CodMdep = codMdep;
scheda.Data = data;
scheda.Rilevatore = rilevatore;
db.Schede.Add(scheda);
await db.SaveChangesAsync();
}
public Task<Scheda?> GetSchedaAsync(int schedaId) =>
db.Schede
.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == schedaId);
public Task<Scheda?> GetSchedaWithIspezioneAsync(int schedaId) =>
db.Schede
.Include(x => x.Ispezione)
.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == schedaId);
public async Task<bool> DeleteSchedaAsync(int schedaId)
{
var scheda = await db.Schede.FirstOrDefaultAsync(x => x.Id == schedaId);
if (scheda is null)
return false;
db.Schede.Remove(scheda);
await db.SaveChangesAsync();
return true;
}
/// <summary>
/// Cancella tutte le schede di una ispezione senza cancellare l'ispezione.
/// </summary>
public async Task<int> DeleteAllSchedeOfIspezioneAsync(string codMdep, DateOnly data, string rilevatore)
{
var schede = await db.Schede
.Where(s =>
s.CodMdep == codMdep &&
s.Data == data &&
s.Rilevatore == rilevatore)
.ToListAsync();
if (schede.Count == 0)
return 0;
db.Schede.RemoveRange(schede);
return await db.SaveChangesAsync();
}
}

View File

@@ -0,0 +1,102 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SteUp.Data.LocalDb;
#nullable disable
namespace SteUp.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20260217143326_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.13");
modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b =>
{
b.Property<string>("CodMdep")
.HasColumnType("TEXT");
b.Property<DateOnly>("Data")
.HasColumnType("TEXT");
b.Property<string>("Rilevatore")
.HasColumnType("TEXT");
b.Property<int>("Stato")
.HasColumnType("INTEGER");
b.HasKey("CodMdep", "Data", "Rilevatore");
b.ToTable("Ispezioni");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ActivityTypeId")
.HasColumnType("TEXT");
b.Property<string>("CodJfas")
.HasColumnType("TEXT");
b.Property<string>("CodMdep")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateOnly>("Data")
.HasColumnType("TEXT");
b.Property<string>("DescrizioneReparto")
.HasColumnType("TEXT");
b.Property<string>("Note")
.HasColumnType("TEXT");
b.Property<string>("Responsabile")
.HasColumnType("TEXT");
b.Property<string>("Rilevatore")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Scadenza")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CodMdep", "Data", "Rilevatore");
b.ToTable("Schede");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b =>
{
b.HasOne("SteUp.Shared.Core.Entities.Ispezione", "Ispezione")
.WithMany("Schede")
.HasForeignKey("CodMdep", "Data", "Rilevatore")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ispezione");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b =>
{
b.Navigation("Schede");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,71 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SteUp.Data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Ispezioni",
columns: table => new
{
CodMdep = table.Column<string>(type: "TEXT", nullable: false),
Data = table.Column<DateOnly>(type: "TEXT", nullable: false),
Rilevatore = table.Column<string>(type: "TEXT", nullable: false),
Stato = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Ispezioni", x => new { x.CodMdep, x.Data, x.Rilevatore });
});
migrationBuilder.CreateTable(
name: "Schede",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
CodJfas = table.Column<string>(type: "TEXT", nullable: true),
CodMdep = table.Column<string>(type: "TEXT", nullable: false),
Data = table.Column<DateOnly>(type: "TEXT", nullable: false),
Rilevatore = table.Column<string>(type: "TEXT", nullable: false),
DescrizioneReparto = table.Column<string>(type: "TEXT", nullable: true),
ActivityTypeId = table.Column<string>(type: "TEXT", nullable: true),
Note = table.Column<string>(type: "TEXT", nullable: true),
Responsabile = table.Column<string>(type: "TEXT", nullable: true),
Scadenza = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Schede", x => x.Id);
table.ForeignKey(
name: "FK_Schede_Ispezioni_CodMdep_Data_Rilevatore",
columns: x => new { x.CodMdep, x.Data, x.Rilevatore },
principalTable: "Ispezioni",
principalColumns: new[] { "CodMdep", "Data", "Rilevatore" },
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Schede_CodMdep_Data_Rilevatore",
table: "Schede",
columns: new[] { "CodMdep", "Data", "Rilevatore" });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Schede");
migrationBuilder.DropTable(
name: "Ispezioni");
}
}
}

View File

@@ -0,0 +1,99 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SteUp.Data.LocalDb;
#nullable disable
namespace SteUp.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
partial class AppDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.13");
modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b =>
{
b.Property<string>("CodMdep")
.HasColumnType("TEXT");
b.Property<DateOnly>("Data")
.HasColumnType("TEXT");
b.Property<string>("Rilevatore")
.HasColumnType("TEXT");
b.Property<int>("Stato")
.HasColumnType("INTEGER");
b.HasKey("CodMdep", "Data", "Rilevatore");
b.ToTable("Ispezioni");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ActivityTypeId")
.HasColumnType("TEXT");
b.Property<string>("CodJfas")
.HasColumnType("TEXT");
b.Property<string>("CodMdep")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateOnly>("Data")
.HasColumnType("TEXT");
b.Property<string>("DescrizioneReparto")
.HasColumnType("TEXT");
b.Property<string>("Note")
.HasColumnType("TEXT");
b.Property<string>("Responsabile")
.HasColumnType("TEXT");
b.Property<string>("Rilevatore")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Scadenza")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CodMdep", "Data", "Rilevatore");
b.ToTable("Schede");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b =>
{
b.HasOne("SteUp.Shared.Core.Entities.Ispezione", "Ispezione")
.WithMany("Schede")
.HasForeignKey("CodMdep", "Data", "Rilevatore")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ispezione");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b =>
{
b.Navigation("Schede");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.13" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.13">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.13" />
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SteUp.Shared\SteUp.Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui" <Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Template.Maui" xmlns:android="clr-namespace:Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;assembly=Microsoft.Maui.Controls"
x:Class="Template.Maui.App"> android:Application.WindowSoftInputModeAdjust="Resize"
x:Class="SteUp.Maui.App">
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>
<Color x:Key="PageBackgroundColor">#512bdf</Color> <Color x:Key="PageBackgroundColor">#dff2ff</Color>
<Color x:Key="PrimaryTextColor">White</Color> <Color x:Key="PrimaryTextColor">White</Color>
<Style TargetType="Label"> <Style TargetType="Label">
@@ -17,7 +18,7 @@
<Style TargetType="Button"> <Style TargetType="Button">
<Setter Property="TextColor" Value="{DynamicResource PrimaryTextColor}" /> <Setter Property="TextColor" Value="{DynamicResource PrimaryTextColor}" />
<Setter Property="FontFamily" Value="OpenSansRegular" /> <Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="BackgroundColor" Value="#2b0b98" /> <Setter Property="BackgroundColor" Value="#dff2ff" />
<Setter Property="Padding" Value="14,10" /> <Setter Property="Padding" Value="14,10" />
</Style> </Style>

15
SteUp.Maui/App.xaml.cs Normal file
View File

@@ -0,0 +1,15 @@
namespace SteUp.Maui
{
public partial class App
{
public App()
{
InitializeComponent();
}
protected override Window CreateWindow(IActivationState? activationState)
{
return new Window(new MainPage());
}
}
}

View File

@@ -0,0 +1,60 @@
using System.Data;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.EntityFrameworkCore;
using SteUp.Data.LocalDb;
using SteUp.Data.LocalDb.EntityServices;
using SteUp.Maui.Core.Services;
using SteUp.Maui.Core.System;
using SteUp.Maui.Core.System.Network;
using SteUp.Shared.Core.Data;
using SteUp.Shared.Core.Data.Contracts;
using SteUp.Shared.Core.Interface;
using SteUp.Shared.Core.Interface.IntegryApi;
using SteUp.Shared.Core.Interface.LocalDb;
using SteUp.Shared.Core.Interface.System;
using SteUp.Shared.Core.Interface.System.Network;
using SteUp.Shared.Core.Services;
namespace SteUp.Maui.Core;
public static class CoreModule
{
public static void RegisterAppServices(this MauiAppBuilder builder)
{
builder.Services.AddSingleton<IFormFactor, FormFactor>();
builder.Services.AddSingleton<IGenericSystemService, GenericSystemService>();
builder.Services.AddScoped<ISteupDataService, SteupDataService>();
}
public static void RegisterIntegryServices(this MauiAppBuilder builder)
{
builder.Services.AddScoped<IIntegryApiService, IntegryApiService>();
builder.Services.AddScoped<IIntegrySteupService, IntegrySteupService>();
}
public static void RegisterSystemService(this MauiAppBuilder builder)
{
builder.Services.AddSingleton<INetworkService, NetworkService>();
}
public static void AddAuthorizationCore(this MauiAppBuilder builder)
{
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<AppAuthenticationStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider>(provider =>
provider.GetRequiredService<AppAuthenticationStateProvider>());
}
public static void RegisterDbServices(this MauiAppBuilder builder)
{
builder.Services.AddSingleton<IDbPathProvider, DbPathProvider>();
builder.Services.AddDbContext<AppDbContext>((sp, options) =>
{
var dbPath = sp.GetRequiredService<IDbPathProvider>().GetDbPath();
options.UseSqlite($"Filename={dbPath}");
});
builder.Services.AddSingleton<IDbInitializer, DbInitializer>();
builder.Services.AddSingleton<IIspezioniService, IspezioniService>();
}
}

View File

@@ -0,0 +1,101 @@
using SteUp.Shared.Core.Dto;
using SteUp.Shared.Core.Interface.System;
namespace SteUp.Maui.Core.Services;
public class AttachedService : IAttachedService
{
public async Task<AttachedDto?> SelectImageFromCamera()
{
var cameraPerm = await Permissions.RequestAsync<Permissions.Camera>();
var storagePerm = await Permissions.RequestAsync<Permissions.StorageWrite>();
if (cameraPerm != PermissionStatus.Granted || storagePerm != PermissionStatus.Granted)
return null;
FileResult? result;
try
{
result = await MediaPicker.Default.CapturePhotoAsync();
}
catch (Exception ex)
{
Console.WriteLine($"Errore cattura foto: {ex.Message}");
SentrySdk.CaptureException(ex);
return null;
}
return result is null ? null : await ConvertToDto(result, AttachedDto.TypeAttached.Image);
}
public async Task<AttachedDto?> SelectImageFromGallery()
{
var storagePerm = await Permissions.RequestAsync<Permissions.StorageRead>();
if (storagePerm != PermissionStatus.Granted)
return null;
FileResult? result;
try
{
result = await MediaPicker.Default.PickPhotoAsync();
}
catch (Exception ex)
{
Console.WriteLine($"Errore selezione galleria: {ex.Message}");
SentrySdk.CaptureException(ex);
return null;
}
return result is null ? null : await ConvertToDto(result, AttachedDto.TypeAttached.Image);
}
private static async Task<AttachedDto> ConvertToDto(FileResult file, AttachedDto.TypeAttached type)
{
var stream = await file.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
return new AttachedDto
{
Name = file.FileName,
Path = file.FullPath,
MimeType = file.ContentType,
DimensionBytes = ms.Length,
FileBytes = ms.ToArray(),
Type = type
};
}
public async Task<string> SaveToTempStorage(Stream file, string fileName, CancellationToken ct = default)
{
ArgumentNullException.ThrowIfNull(file);
if (file.CanSeek)
file.Position = 0;
fileName = Path.GetFileName(fileName);
var dir = FileSystem.CacheDirectory;
var filePath = Path.Combine(dir, fileName);
await using var fileStream = File.Create(filePath);
await file.CopyToAsync(fileStream, ct);
return filePath;
}
public Task OpenFile(string fileName, string filePath)
{
#if IOS
throw new NotImplementedException();
#else
return Launcher.OpenAsync(new OpenFileRequest
{
Title = "Apri file",
File = new ReadOnlyFile(filePath)
});
#endif
}
}

View File

@@ -1,6 +1,6 @@
using Template.Shared.Interfaces; using SteUp.Shared.Core.Interface;
namespace Template.Maui.Services; namespace SteUp.Maui.Core.Services;
public class FormFactor : IFormFactor public class FormFactor : IFormFactor
{ {

View File

@@ -0,0 +1,15 @@
using SteUp.Shared.Core.Interface.System;
namespace SteUp.Maui.Core.System;
public class GenericSystemService : IGenericSystemService
{
public string GetCurrentAppVersion()
{
#if DEBUG
return $"v{AppInfo.VersionString} [DEBUG]";
#else
return $"v{AppInfo.VersionString}";
#endif
}
}

View File

@@ -0,0 +1,12 @@
using SteUp.Shared.Core.Interface.System.Network;
namespace SteUp.Maui.Core.System.Network;
public class NetworkService : INetworkService
{
public bool ConnectionAvailable { get; set; }
public bool IsNetworkAvailable() =>
Connectivity.Current.NetworkAccess == NetworkAccess.Internet;
}

View File

@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Template.Maui" xmlns:shared="clr-namespace:SteUp.Shared;assembly=SteUp.Shared"
xmlns:shared="clr-namespace:Template.Shared;assembly=Template.Shared" x:Class="SteUp.Maui.MainPage"
x:Class="Template.Maui.MainPage"
BackgroundColor="{DynamicResource PageBackgroundColor}"> BackgroundColor="{DynamicResource PageBackgroundColor}">
<BlazorWebView x:Name="blazorWebView" HostPage="wwwroot/index.html"> <BlazorWebView x:Name="blazorWebView" HostPage="wwwroot/index.html">

View File

@@ -1,4 +1,4 @@
namespace Template.Maui namespace SteUp.Maui
{ {
public partial class MainPage : ContentPage public partial class MainPage : ContentPage
{ {

54
SteUp.Maui/MauiProgram.cs Normal file
View File

@@ -0,0 +1,54 @@
using CommunityToolkit.Maui;
using IntegryApiClient.MAUI;
using Microsoft.Extensions.Logging;
using MudBlazor.Services;
using MudExtensions.Services;
using SteUp.Maui.Core;
using SteUp.Maui.Core.Services;
using SteUp.Shared;
using SteUp.Shared.Core.Interface;
namespace SteUp.Maui
{
public static class MauiProgram
{
private const string AppToken = "4fef1843-793d-499b-a7ed-1edd8cac465c";
public static MauiApp CreateMauiApp()
{
InteractiveRenderSettings.ConfigureBlazorHybridRenderModes();
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseIntegry(appToken: AppToken, useLoginAzienda: true)
.UseMauiCommunityToolkit()
.UseSentry(options =>
{
options.Dsn = "https://c1ff03e3d1d2dd973a1ce73c58f92a8d@o4508499810254848.ingest.de.sentry.io/4510900455866448";
#if DEBUG
options.Debug = true;
#endif
options.TracesSampleRate = 1.0;
})
.ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); });
builder.Services.AddMauiBlazorWebView();
builder.Services.AddMudServices();
builder.Services.AddMudExtensions();
#if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools();
builder.Logging.AddDebug();
#endif
builder.AddAuthorizationCore();
builder.RegisterAppServices();
builder.RegisterIntegryServices();
builder.RegisterSystemService();
builder.RegisterDbServices();
return builder.Build();
}
}
}

View File

@@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <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> <application
android:allowBackup="true"
android:icon="@mipmap/appicon"
android:usesCleartextTraffic="true"
android:supportsRtl="true">
</application>
<!-- Rete -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
</manifest> </manifest>

View File

@@ -0,0 +1,14 @@
using Android.App;
using Android.Content.PM;
namespace SteUp.Maui
{
[Activity(
Theme = "@style/Maui.SplashTheme",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode |
ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
}
}

View File

@@ -1,7 +1,7 @@
using Android.App; using Android.App;
using Android.Runtime; using Android.Runtime;
namespace Template.Maui namespace SteUp.Maui
{ {
[Application] [Application]
public class MainApplication : MauiApplication public class MainApplication : MauiApplication

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#ec4c41</color>
<color name="colorPrimaryDark">#d02315</color>
<color name="colorAccent">#d02315</color>
</resources>

View File

@@ -1,7 +1,7 @@
using Foundation; using Foundation;
using Template.Maui; using SteUp.Maui;
namespace Template.Maui namespace SteUp.Maui
{ {
[Register("AppDelegate")] [Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate public class AppDelegate : MauiUIApplicationDelegate

View File

@@ -1,7 +1,7 @@
using ObjCRuntime; using ObjCRuntime;
using UIKit; using UIKit;
namespace Template.Maui namespace SteUp.Maui
{ {
public class Program public class Program
{ {

View File

@@ -2,7 +2,7 @@ using System;
using Microsoft.Maui; using Microsoft.Maui;
using Microsoft.Maui.Hosting; using Microsoft.Maui.Hosting;
namespace Template.Maui namespace SteUp.Maui
{ {
internal class Program : MauiApplication internal class Program : MauiApplication
{ {

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest package="maui-application-id-placeholder" version="0.0.0" api-version="8" xmlns="http://tizen.org/ns/packages"> <manifest package="maui-application-id-placeholder" version="0.0.0" api-version="8" xmlns="http://tizen.org/ns/packages">
<profile name="common" /> <profile name="common" />
<ui-application appid="maui-application-id-placeholder" exec="Template.Maui.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single"> <ui-application appid="maui-application-id-placeholder" exec="SteUp.Maui.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single">
<label>maui-application-title-placeholder</label> <label>maui-application-title-placeholder</label>
<icon>maui-appicon-placeholder</icon> <icon>maui-appicon-placeholder</icon>
<metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" /> <metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />

View File

@@ -3,7 +3,7 @@ using Microsoft.UI.Xaml;
// To learn more about WinUI, the WinUI project structure, // To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info. // and more about our project templates, see: http://aka.ms/winui-project-info.
namespace Template.Maui.WinUI namespace SteUp.Maui.WinUI
{ {
/// <summary> /// <summary>
/// Provides application-specific behavior to supplement the default Application class. /// Provides application-specific behavior to supplement the default Application class.

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="Template.Maui.WinUI.app"/> <assemblyIdentity version="1.0.0.0" name="SteUp.Maui.WinUI.app"/>
<application xmlns="urn:schemas-microsoft-com:asm.v3"> <application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings> <windowsSettings>

View File

@@ -1,6 +1,6 @@
using Foundation; using Foundation;
namespace Template.Maui namespace SteUp.Maui
{ {
[Register("AppDelegate")] [Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate public class AppDelegate : MauiUIApplicationDelegate

View File

@@ -1,7 +1,7 @@
using ObjCRuntime; using ObjCRuntime;
using UIKit; using UIKit;
namespace Template.Maui namespace SteUp.Maui
{ {
public class Program public class Program
{ {

View File

@@ -0,0 +1 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 456 456" width="456" height="456"><defs><image width="456" height="456" id="img1" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAcgAAAHIAQMAAADwb+ipAAAAAXNSR0IB2cksfwAAAANQTFRF/ezqqHJq3wAAAGhJREFUeJztyzENAAAMA6DVv+l5aHrCT64V0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN0zRN05zNB6OcAcm2KNubAAAAAElFTkSuQmCC"/></defs><style></style><use href="#img1" x="0" y="0"/></svg>

After

Width:  |  Height:  |  Size: 493 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -0,0 +1,131 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFrameworks>$(TargetFrameworks);net9.0-android</TargetFrameworks>
<TargetFrameworks>$(TargetFrameworks);net9.0-ios</TargetFrameworks>
<!-- <TargetFrameworks>$(TargetFrameworks);net9.0-maccatalyst</TargetFrameworks>-->
<!-- <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks>-->
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net9.0-tizen</TargetFrameworks> -->
<!-- Note for MacCatalyst:
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
<OutputType>Exe</OutputType>
<RootNamespace>SteUp.Maui</RootNamespace>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<EnableDefaultCssItems>false</EnableDefaultCssItems>
<Nullable>enable</Nullable>
<!-- Display name -->
<ApplicationTitle>SteUP</ApplicationTitle>
<!-- App Identifier -->
<ApplicationId>it.integry.SteUp</ApplicationId>
<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
<!-- <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">-->
<!-- 14.0-->
<!-- </SupportedOSPlatformVersion>-->
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">24.0</SupportedOSPlatformVersion>
<!-- <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>-->
<!-- <TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>-->
<!--slower build, faster runtime in DEBUG-->
<!-- <_MauiForceXamlCForDebug Condition="'$(Configuration)' == 'Debug'">true</_MauiForceXamlCForDebug> -->
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<DefineConstants>$(DefineConstants);PLATFORM</DefineConstants>
<SupportedOSPlatformVersion>26.0</SupportedOSPlatformVersion>
<TargetPlatformVersion>35</TargetPlatformVersion>
<!--<EmbedAssembliesIntoApk Condition="'$(Configuration)' == 'Debug'">true</EmbedAssembliesIntoApk>
<AndroidPackageFormats Condition="'$(Configuration)' == 'Release'">aab</AndroidPackageFormats>
<AndroidLinkTool>r8</AndroidLinkTool>
<AndroidLinkTool>proguard</AndroidLinkTool>-->
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android' AND '$(Configuration)' == 'Debug'">
<!--these help speed up android builds-->
<!--
<RuntimeIdentifier>android-arm64</RuntimeIdentifier>
<AndroidEnableProfiler>true</AndroidEnableProfiler>
<AndroidPackageFormat>aab</AndroidPackageFormat>
-->
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios' AND '$(Configuration)' == 'Debug'">
<!--forces the simulator to pickup entitlements-->
<EnableCodeSigning>true</EnableCodeSigning>
<CodesignRequireProvisioningProfile>true</CodesignRequireProvisioningProfile>
<DisableCodesignVerification>true</DisableCodesignVerification>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios' OR $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<SupportedOSPlatformVersion>14.2</SupportedOSPlatformVersion>
<DefineConstants>$(DefineConstants);APPLE;PLATFORM</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)'=='net9.0-ios'">
<CodesignKey>Apple Development: Massimo Fausto Morelli (6C2CUM53BT)</CodesignKey>
<CodesignProvision>VS: WildCard Development</CodesignProvision>
</PropertyGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios' OR $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<!--
<BundleResource Include="Platforms\iOS\PrivacyInfo.xcprivacy" LogicalName="PrivacyInfo.xcprivacy" />
<CustomEntitlements Include="keychain-access-groups" Type="StringArray" Value="%24(AppIdentifierPrefix)$(ApplicationId)" Visible="false" />
<CustomEntitlements Include="aps-environment" Type="string" Value="development" Condition="'$(Configuration)' == 'Debug'" Visible="false" />
<CustomEntitlements Include="aps-environment" Type="string" Value="production" Condition="'$(Configuration)' == 'Release'" Visible="false" />
-->
</ItemGroup>
<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#FDECEA" />
<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#FDECEA" BaseSize="128,128" />
<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" />
<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Maui" Version="12.2.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="IntegryApiClient.MAUI" Version="1.2.3" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.13" />
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.120" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="9.0.120" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="9.0.120" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.13" />
<PackageReference Include="Sentry.Maui" Version="5.16.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SteUp.Shared\SteUp.Shared.csproj" />
<ProjectReference Include="..\SteUp.Data\SteUp.Data.csproj" />
</ItemGroup>
</Project>

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"/>
<title>SteUp.Maui</title>
<base href="/"/>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap"
rel="stylesheet">
<link href="_content/SteUp.Shared/css/bootstrap/bootstrap.min.css" rel="stylesheet">
<link href="_content/SteUp.Shared/css/bootstrap/bootstrap-icons.min.css" rel="stylesheet"/>
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet"/>
<link href="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="_content/SteUp.Shared/css/remixicon/remixicon.css"/>
<link rel="stylesheet" href="_content/SteUp.Shared/css/app.css"/>
<link rel="stylesheet" href="_content/SteUp.Shared/css/form.css"/>
<link rel="stylesheet" href="_content/SteUp.Shared/css/default-theme.css"/>
<link rel="stylesheet" href="_content/SteUp.Shared/css/custom-mudBlazor.css"/>
<link rel="stylesheet" href="SteUp.Maui.styles.css"/>
<link rel="icon" type="image/png" href="favicon.png"/>
</head>
<body>
<div class="status-bar-safe-area"></div>
<div id="app">
<div class="spinner-container">
<span class="loader"></span>
</div>
</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webview.js" autostart="false"></script>
<script src="_content/SteUp.Shared/js/bootstrap/bootstrap.bundle.min.js"></script>
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
<script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script>
<script src="_content/SteUp.Shared/js/main.js"></script>
</body>
</html>

View File

@@ -0,0 +1,78 @@
@using SteUp.Shared.Core.Helpers
@inject IJSRuntime Js
<div class="@(Back ? "" : "container") header">
<div class="header-content @(Back ? "with-back" : "no-back")">
@if (!SmallHeader)
{
if (Back)
{
<div class="left-section">
<MudButton StartIcon="@(!Cancel ? Icons.Material.Outlined.ArrowBackIosNew : "")"
OnClick="@GoBack"
Color="Color.Info"
Style="text-transform: none"
Variant="Variant.Text">
@BackTo
</MudButton>
</div>
}
<h3 class="page-title">@Title</h3>
<div class="right-section">
@if (!LabelSave.IsNullOrEmpty())
{
<MudButton OnClick="@OnSave"
Color="Color.Info"
Style="text-transform: none"
Variant="Variant.Text">
@LabelSave
</MudButton>
}
</div>
}
else
{
<div class="title">
<MudText Typo="Typo.h6">
<b>@Title</b>
</MudText>
<MudIconButton Icon="@Icons.Material.Filled.Close" OnClick="@GoBack" />
</div>
}
</div>
</div>
@code{
[Parameter] public string? Title { get; set; }
[Parameter] public bool Back { get; set; }
[Parameter] public string BackTo { get; set; } = "";
[Parameter] public EventCallback OnFilterToggle { get; set; }
[Parameter] public bool Cancel { get; set; }
[Parameter] public EventCallback OnCancel { get; set; }
[Parameter] public string? LabelSave { get; set; }
[Parameter] public EventCallback OnSave { get; set; }
[Parameter] public bool SmallHeader { get; set; }
protected override void OnParametersSet()
{
Back = !Back ? !Back && Cancel : Back;
BackTo = Cancel ? "Annulla" : BackTo;
}
private async Task GoBack()
{
if (Cancel)
{
await OnCancel.InvokeAsync();
return;
}
await Js.InvokeVoidAsync("goBack");
}
}

View File

@@ -0,0 +1,31 @@
.header {
min-height: var(--mh-header);
width: 100%;
display: flex;
align-items: center;
}
.header-content {
width: 100%;
line-height: normal;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
}
.header-content > .title { width: 100%; }
.header-content.with-back .page-title {
position: absolute;
left: 50%;
transform: translateX(-50%);
margin: 0;
font-size: larger;
}
.left-section ::deep button, .right-section ::deep button { font-size: 1.1rem; }
.left-section ::deep .mud-button-icon-start { margin-right: 3px !important; }
.header-content.no-back .page-title { margin: 0; }

View File

@@ -0,0 +1,173 @@
@using System.Globalization
@using SteUp.Shared.Components.SingleElements
@using SteUp.Shared.Core.Interface.IntegryApi
@using SteUp.Shared.Core.Interface.System.Network
@inherits LayoutComponentBase
@inject INetworkService NetworkService
@inject IIntegryApiService IntegryApiService
<MudThemeProvider Theme="_currentTheme" @ref="@_mudThemeProvider" @bind-IsDarkMode="@IsDarkMode" />
<MudPopoverProvider/>
<MudDialogProvider/>
<MudSnackbarProvider/>
<ConnectionState IsNetworkAvailable="IsNetworkAvailable" ServicesIsDown="ServicesIsDown" ShowWarning="ShowWarning" />
<div class="page">
<NavMenu/>
<main>
<article>
@Body
</article>
</main>
</div>
@code {
private MudThemeProvider _mudThemeProvider = null!;
private bool IsDarkMode { get; set; }
private string _mainContentClass = "";
//Connection state
private bool _isNetworkAvailable;
private bool _servicesIsDown;
private bool _showWarning;
private DateTime _lastApiCheck = DateTime.MinValue;
private const int DelaySeconds = 90;
private CancellationTokenSource? _cts;
private bool ServicesIsDown
{
get => _servicesIsDown;
set
{
if (_servicesIsDown == value) return;
_servicesIsDown = value;
StateHasChanged();
}
}
private bool IsNetworkAvailable
{
get => _isNetworkAvailable;
set
{
if (_isNetworkAvailable == value) return;
_isNetworkAvailable = value;
StateHasChanged();
}
}
private bool ShowWarning
{
get => _showWarning;
set
{
if (_showWarning == value) return;
_showWarning = value;
StateHasChanged();
}
}
private readonly MudTheme _currentTheme = new()
{
PaletteLight = new PaletteLight()
{
Primary = "#ec4c41",
Secondary = "#002339",
Tertiary = "#dff2ff",
TextPrimary = "#000"
},
PaletteDark = new PaletteDark
{
Primary = "#ec4c41",
Secondary = "#002339",
Tertiary = "#dff2ff",
Surface = "#000406",
Background = "#000406",
TextPrimary = "#fff",
GrayDark = "#E0E0E0"
}
};
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// if (firstRender)
// {
// var isDarkMode = LocalStorage.GetString("isDarkMode");
// if (isDarkMode == null && _mudThemeProvider != null)
// {
// IsDarkMode = await _mudThemeProvider.GetSystemPreference();
// await _mudThemeProvider.WatchSystemPreference(OnSystemPreferenceChanged);
// LocalStorage.SetString("isDarkMode", IsDarkMode.ToString());
// StateHasChanged();
// }
// else
// {
// IsDarkMode = bool.Parse(isDarkMode!);
// }
// if (IsDarkMode)
// {
// _mainContentClass += "is-dark";
// StateHasChanged();
// }
// }
}
private async Task OnSystemPreferenceChanged(bool newValue)
{
IsDarkMode = newValue;
}
protected override void OnInitialized()
{
_cts = new CancellationTokenSource();
_ = CheckConnectionState(_cts.Token);
var culture = new CultureInfo("it-IT", false);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
private Task CheckConnectionState(CancellationToken token)
{
return Task.Run(async () =>
{
while (!token.IsCancellationRequested)
{
var isNetworkAvailable = NetworkService.IsNetworkAvailable();
var servicesDown = ServicesIsDown;
if (isNetworkAvailable && (DateTime.UtcNow - _lastApiCheck).TotalSeconds >= DelaySeconds)
{
servicesDown = !await IntegryApiService.SystemOk();
_lastApiCheck = DateTime.UtcNow;
}
await InvokeAsync(async () =>
{
IsNetworkAvailable = isNetworkAvailable;
ServicesIsDown = servicesDown;
await Task.Delay(1500, token);
ShowWarning = !(IsNetworkAvailable && !ServicesIsDown);
NetworkService.ConnectionAvailable = !ShowWarning;
});
await Task.Delay(500, token);
}
}, token);
}
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
}

View File

@@ -0,0 +1,99 @@
@using SteUp.Shared.Core.Interface.System.Network
@inject INetworkService NetworkService
@inject IDialogService Dialog
<div
class="container animated-navbar @(IsVisible ? "show-nav" : "hide-nav") @(IsVisible ? PlusVisible ? "with-plus" : "without-plus" : "with-plus")">
<nav class="navbar @(IsVisible ? PlusVisible ? "with-plus" : "without-plus" : "with-plus")">
<div class="container-navbar">
<ul class="navbar-nav flex-row nav-justified align-items-center w-100 text-center">
<li class="nav-item">
<NavLink class="nav-link" href="ispezioni" Match="NavLinkMatch.All">
<div class="d-flex flex-column">
<i class="ri-file-list-3-line"></i>
<span>Ispezioni</span>
</div>
</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="user" Match="NavLinkMatch.All">
<div class="d-flex flex-column">
<i class="ri-user-line"></i>
<span>Profilo</span>
</div>
</NavLink>
</li>
</ul>
</div>
@if (PlusVisible)
{
<MudMenu PopoverClass="custom_popover" AnchorOrigin="Origin.TopLeft" TransformOrigin="Origin.BottomRight">
<ActivatorContent>
<MudFab Class="custom-plus-button" OnClick="OnOpenMenu" Color="Color.Surface" Size="Size.Medium" IconSize="Size.Medium"
IconColor="Color.Primary" StartIcon="@Icons.Material.Filled.Add"/>
</ActivatorContent>
<ChildContent>
@if (SchedaVisible)
{
<MudMenuItem Disabled="!NetworkService.IsNetworkAvailable()" OnClick="@NewScheda">
Nuova scheda
</MudMenuItem>
}
else
{
<MudMenuItem Disabled="!NetworkService.IsNetworkAvailable()" OnClick="@NewActivity">
Nuova ispezione
</MudMenuItem>
}
</ChildContent>
</MudMenu>
}
</nav>
</div>
@code
{
private bool IsVisible { get; set; } = true;
private bool PlusVisible { get; set; } = true;
private bool SchedaVisible { get; set; }
protected override Task OnInitializedAsync()
{
NavigationManager.LocationChanged += (_, args) =>
{
var location = args.Location.Remove(0, NavigationManager.BaseUri.Length);
var newIsVisible = new List<string> { "ispezioni", "ispezione", "user" }
.Contains(location);
var newPlusVisible = new List<string> { "ispezioni", "ispezione", "user" }
.Contains(location);
if (IsVisible == newIsVisible && PlusVisible == newPlusVisible) return;
IsVisible = newIsVisible;
PlusVisible = newPlusVisible;
StateHasChanged();
};
return Task.CompletedTask;
}
private void NewActivity()
{
_ = ModalHelper.OpenSelectShop(Dialog);
}
private void NewScheda()
{
_ = ModalHelper.OpenFormScheda(Dialog);
}
private void OnOpenMenu()
{
var location = NavigationManager.Uri.Remove(0, NavigationManager.BaseUri.Length);
SchedaVisible = new List<string> { "ispezione" }.Contains(location);
StateHasChanged();
}
}

View File

@@ -0,0 +1,97 @@
.animated-navbar {
background: transparent;
position: fixed;
bottom: 0;
width: 100%;
z-index: 1001;
transition: all 0.3s ease-in-out;
}
.animated-navbar.show-nav { transform: translateY(0); }
.animated-navbar.hide-nav { transform: translateY(150%); }
.animated-navbar.with-plus { margin-left: 30px; }
.navbar {
padding-bottom: 1rem;
padding-top: 0 !important;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: end;
transition: all 0.3s ease-in-out;
}
.navbar.with-plus { transform: translateX(-30px); }
.navbar.without-plus {
transform: translateX(0);
justify-content: center;
}
.container-navbar {
background: var(--mud-palette-surface);
border-radius: 50px;
padding: 0 10px;
box-shadow: var(--custom-box-shadow);
transition: all 0.3s ease-in-out;
}
.nav-item { font-size: 0.9rem; }
.nav-item.plus-button {
position: relative;
bottom: 15px;
}
.navbar ::deep .custom-plus-button .mud-icon-root {
transition: .5s;
transform: rotate(0);
font-size: 2rem;
}
.navbar ::deep .custom-plus-button {
background: var(--mud-palette-surface);
box-shadow: var(--custom-box-shadow);
transition: all 0.3s ease-in-out;
}
.navbar ::deep .custom-plus-button:focus .mud-icon-root { transform: rotate(225deg); }
.nav-item ::deep a {
display: flex;
align-items: center;
line-height: 1.2;
justify-content: center;
padding-top: .25rem !important;
padding-bottom: .25rem !important;
}
.nav-item ::deep a > div {
-webkit-transition: all .1s ease-out;
transition: all .1s ease-out;
min-width: 75px;
}
.nav-item ::deep a.active > div { color: var(--mud-palette-primary); }
.nav-item ::deep a.active > div > i {
/*background-color: color-mix(in srgb, var(--mud-palette-primary) 20%, transparent);*/
border-radius: 10px;
}
.nav-item ::deep a.active > div > span { font-weight: 800; }
.nav-item ::deep a:not(.active) > div {
color: var(--mud-palette-text-primary);
}
.nav-item ::deep a i { font-size: 1.65rem; }
.nav-item ::deep a span {
font-size: 0.8rem;
font-weight: 500;
}
@supports (-webkit-touch-callout: none) { .navbar { padding-bottom: env(safe-area-inset-bottom); } }

View File

@@ -0,0 +1,24 @@
@using SteUp.Shared.Components.Layout.Spinner
<MudOverlay Visible="VisibleOverlay" LightBackground="true">
@if (SuccessAnimation)
{
<div class="success-checkmark">
<div class="check-icon">
<span class="icon-line line-tip"></span>
<span class="icon-line line-long"></span>
<div class="icon-circle"></div>
<div class="icon-fix"></div>
</div>
</div>
}
else
{
<SpinnerLayout/>
}
</MudOverlay>
@code {
[Parameter] public required bool SuccessAnimation { get; set; }
[Parameter] public required bool VisibleOverlay { get; set; }
}

View File

@@ -0,0 +1,8 @@
<div class="spinner-container @(FullScreen ? "" : "not-fullScreen")">
<span class="loader"></span>
</div>
@code
{
[Parameter] public bool FullScreen { get; set; } = true;
}

View File

@@ -0,0 +1,43 @@
.spinner-container {
display: flex;
justify-content: center;
height: calc(100vh - 10.1rem);
align-items: center;
color: var(--mud-palette-primary);
}
.not-fullScreen {
height: auto !important;
padding: 2rem 0 !important;
}
.loader {
width: 50px;
aspect-ratio: 1;
border-radius: 50%;
border: 8px solid #0000;
border-right-color: var(--mud-palette-primary);
position: relative;
animation: l24 1s infinite linear;
}
.loader:before,
.loader:after {
content: "";
position: absolute;
inset: -8px;
border-radius: 50%;
border: inherit;
animation: inherit;
animation-duration: 2s;
}
.loader:after {
animation-duration: 4s;
}
@keyframes l24 {
100% {
transform: rotate(1turn)
}
}

View File

@@ -0,0 +1,12 @@
@page "/"
@using SteUp.Shared.Components.Layout.Spinner
@attribute [Authorize]
<SpinnerLayout FullScreen="true"/>
@code {
protected override void OnInitialized()
{
NavigationManager.NavigateTo("/ispezioni");
}
}

View File

@@ -0,0 +1,17 @@
@page "/ispezione"
@using SteUp.Shared.Components.Layout
@using SteUp.Shared.Components.SingleElements.Card
<HeaderLayout Title="Ispezione" BackTo="Indietro" Back="true"/>
<div class="container content pb-safe-area">
<InspectionCard Ispezione="SteupDataService.InspectionPageState.Ispezione"/>
</div>
@code {
protected override async Task OnInitializedAsync()
{
}
}

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,52 @@
@page "/ispezioni"
@attribute [Authorize]
@using SteUp.Shared.Components.Layout
@using SteUp.Shared.Components.Layout.Overlay
@using SteUp.Shared.Components.SingleElements
@using SteUp.Shared.Components.SingleElements.Card
@using SteUp.Shared.Core.Entities
@using SteUp.Shared.Core.Interface.LocalDb
@inject IIspezioniService IspezioniService
<HeaderLayout Title="Ispezioni"/>
<div class="container ispezioni">
@if (Ispezioni.IsNullOrEmpty())
{
<NoDataAvailable Text="Nessuna ispezione effettuata" ImageSource="_content/SteUp.Shared/images/undraw_file-search_cbur.svg"/>
}
else
{
<Virtualize Items="Ispezioni" Context="ispezione">
<InspectionCard Ispezione="ispezione" CompactView="true" OnClick="@OnClickIspezione"/>
</Virtualize>
}
</div>
<SpinnerOverlay VisibleOverlay="VisibleOverlay"/>
@code{
private List<Ispezione> Ispezioni { get; set; } = [];
private bool VisibleOverlay { get; set; } = true;
protected override async Task OnInitializedAsync()
{
await LoadData();
VisibleOverlay = false;
StateHasChanged();
}
private async Task LoadData()
{
Ispezioni = await IspezioniService.GetAllIspezioniWithSchedeAsync();
}
private void OnClickIspezione(Ispezione ispezione)
{
SteupDataService.InspectionPageState.Ispezione = ispezione;
NavigationManager.NavigateTo("/ispezione");
}
}

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,116 @@
@page "/login"
@using SteUp.Shared.Components.Layout.Spinner
@using SteUp.Shared.Core.Interface.System
@using SteUp.Shared.Core.Services
@inject IUserAccountService UserAccountService
@inject AppAuthenticationStateProvider AuthenticationStateProvider
@inject IGenericSystemService GenericSystemService
@if (Spinner)
{
<SpinnerLayout/>
}
else
{
<div class="login-page">
<div class="container container-top-logo">
<img src="_content/SteUp.Shared/images/logo_steup.svg" class="logo" alt="sales book">
</div>
<div class="container container-login">
<div class="login-form-container">
<div class="input-group">
<MudTextField @bind-Value="UserData.Username" Label="Username" Variant="Variant.Outlined"/>
</div>
<div class="input-group">
<MudTextField InputType="@_passwordInput" @bind-Value="UserData.Password" Label="Password" Variant="Variant.Outlined" Adornment="Adornment.End" AdornmentIcon="@_passwordInputIcon" OnAdornmentClick="ShowPassword" AdornmentAriaLabel="Show Password"/>
</div>
<div class="input-group mb-2">
<MudTextField @bind-Value="UserData.CodHash" Label="Profilo azienda" Variant="Variant.Outlined"/>
</div>
<MudButton OnClick="@SignInUser" Color="Color.Primary" Variant="Variant.Filled">Login</MudButton>
@if (_attemptFailed)
{
<MudAlert Class="my-3" Dense="true" Severity="Severity.Error" Variant="Variant.Filled">@ErrorMessage</MudAlert>
}
</div>
<div class="my-4 login-footer">
<span>@GenericSystemService.GetCurrentAppVersion() | Powered by</span>
<img src="_content/SteUp.Shared/images/logoIntegry.svg" class="img-fluid" alt="Integry">
</div>
</div>
</div>
}
@code {
private SignIn UserData { get; } = new();
private bool Spinner { get; set; }
private string ErrorMessage { get; set; } = "";
private bool _attemptFailed;
private bool _isShow;
private InputType _passwordInput = InputType.Password;
private string _passwordInputIcon = Icons.Material.Rounded.VisibilityOff;
private void ShowPassword()
{
if (_isShow)
{
_isShow = false;
_passwordInputIcon = Icons.Material.Rounded.VisibilityOff;
_passwordInput = InputType.Password;
}
else
{
_isShow = true;
_passwordInputIcon = Icons.Material.Rounded.Visibility;
_passwordInput = InputType.Text;
}
}
protected override void OnInitialized()
{
UserData.CodHash = LocalStorage.GetString("codHash");
StateHasChanged();
}
private async Task SignInUser()
{
_attemptFailed = false;
if (!string.IsNullOrEmpty(UserData.Username) && !string.IsNullOrEmpty(UserData.Password) && !string.IsNullOrEmpty(UserData.CodHash))
{
Spinner = true;
StateHasChanged();
try
{
await UserAccountService.Login(UserData.Username, UserData.Password, UserData.CodHash);
AuthenticationStateProvider.NotifyAuthenticationState(); //Chiamato per forzare il refresh
await SteupDataService.Init();
LocalStorage.SetString("codHash", UserData.CodHash);
NavigationManager.NavigateTo("/");
StateHasChanged();
}
catch (Exception e)
{
Spinner = false;
StateHasChanged();
ErrorMessage = e.Message;
_attemptFailed = true;
Console.WriteLine(e);
}
}
}
public class SignIn
{
public string? Username { get; set; }
public string? Password { get; set; }
public string? CodHash { get; set; }
}
}

View File

@@ -0,0 +1,54 @@
.login-page {
height: 100%;
display: flex;
flex-direction: column;
background: var(--mud-palette-surface);
}
.container-top-logo > .logo {
width: 50%;
}
.container-login > span {
font-size: large;
font-weight: 900;
text-align: center;
}
.container-top-logo {
height: 35vh;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
.login-form-container {
display: flex;
flex-direction: column;
gap: 1rem;
}
.container-login {
height: 100%;
display: flex;
flex-direction: column;
padding: 4px 16px 16px;
justify-content: space-between;
}
.login-footer {
width: 100%;
display: flex;
justify-content: center;
}
.login-footer span {
font-size: 9px;
color: var(--mud-palette-gray-darker);
}
.login-footer img {
height: 15px;
margin-left: 4px;
}

View File

@@ -0,0 +1,115 @@
@page "/user"
@attribute [Authorize]
@using SteUp.Shared.Components.Layout
@using SteUp.Shared.Components.SingleElements
@using SteUp.Shared.Core.Authorization.Enum
@using SteUp.Shared.Core.Helpers
@using SteUp.Shared.Core.Interface.System.Network
@using SteUp.Shared.Core.Services
@using SteUp.Shared.Core.Utility
@inject AppAuthenticationStateProvider AuthenticationStateProvider
@inject INetworkService NetworkService
<HeaderLayout Title="Profilo"/>
@if (IsLoggedIn)
{
<div class="container content pb-safe-area">
<div class="container-primary-info">
<div class="section-primary-info">
<MudAvatar Style="height: 70px; width: 70px; font-size: 2rem; font-weight: bold"
Color="Color.Secondary">
@UtilityString.ExtractInitials(UserSession.User.Fullname)
</MudAvatar>
<div class="personal-info">
<span class="info-nome">@UserSession.User.Fullname</span>
@if (UserSession.User.KeyGroup is not null)
{
<span
class="info-section">@(((KeyGroupEnum)UserSession.User.KeyGroup).ConvertToHumanReadable())</span>
}
</div>
</div>
<div class="divider"></div>
<div class="section-info">
<div class="section-personal-info">
<div>
<span class="info-title">Profilo azienda</span>
<span class="info-text">@CodHash</span>
</div>
</div>
<div class="section-personal-info">
<div>
<span class="info-title">Status</span>
@if (NetworkService.ConnectionAvailable)
{
<div class="status online">
<i class="ri-wifi-line"></i>
<span>Online</span>
</div>
}
else
{
<div class="status offline">
<i class="ri-wifi-off-line"></i>
<span>Offline</span>
</div>
}
</div>
</div>
</div>
</div>
<div class="container-button">
<MudButton Class="button-settings green-icon"
FullWidth="true"
StartIcon="@Icons.Material.Outlined.Sync"
Size="Size.Medium"
OnClick="@UpdateDb"
Variant="Variant.Outlined">
Sincronizza ispezioni
</MudButton>
</div>
<div class="container-button">
<MudButton Class="button-settings exit"
FullWidth="true"
Color="Color.Error"
Size="Size.Medium"
OnClick="@Logout"
Variant="Variant.Outlined">
Esci
</MudButton>
</div>
<AppVersion/>
</div>
}
@code {
private bool IsLoggedIn { get; set; }
private string? CodHash { get; set; } = "";
protected override async Task OnInitializedAsync()
{
IsLoggedIn = await UserSession.IsLoggedIn();
CodHash = LocalStorage.GetString("codHash");
StateHasChanged();
}
private void UpdateDb()
{
}
private async Task Logout()
{
await AuthenticationStateProvider.SignOut();
IsLoggedIn = await UserSession.IsLoggedIn();
StateHasChanged();
}
}

View File

@@ -0,0 +1,83 @@
.container-primary-info {
background: var(--light-card-background);
width: 100%;
margin-bottom: 2rem;
border-radius: 12px;
}
.container-primary-info .divider {
margin: 0 0 0 7rem;
width: unset;
}
.section-primary-info {
display: flex;
flex-direction: row;
align-items: center;
gap: 1.5rem;
padding: .8rem 1.2rem .4rem;
}
.personal-info {
display: flex;
flex-direction: column;
align-items: flex-start;
line-height: normal;
}
.info-nome {
color: var(--mud-palette-text-primary);
font-weight: 800;
font-size: x-large;
}
.info-section {
color: var(--mud-palette-gray-default);
font-size: medium;
font-weight: 600;
}
.section-info {
display: flex;
justify-content: space-between;
flex-direction: row;
padding: .4rem 1.2rem .8rem;
}
.section-personal-info {
display: flex;
flex-direction: column;
}
.section-personal-info > div {
display: flex;
flex-direction: column;
line-height: normal;
margin: .25rem 0;
}
.info-title {
color: var(--mud-palette-gray-darker);
font-weight: 800;
}
.info-text {
color: var(--mud-palette-text-secondary);
font-weight: 700;
font-size: small;
}
.content ::deep .user-button { border: 1px solid var(--card-border-color) !important; }
.user-button > i { font-size: large; }
.user-button > span {
font-size: medium;
font-weight: 600;
}
.status { font-weight: 700; }
.status.online { color: var(--mud-palette-success); }
.status.offline { color: var(--mud-palette-error); }

View File

@@ -0,0 +1,53 @@
@using SteUp.Shared.Components.SingleElements.Modal.ExceptionModal
@inject NavigationManager NavigationManager
<ErrorBoundary @ref="ErrorBoundary">
<ChildContent>
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Routes).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)">
<Authorizing>
<p>Authorizing page</p>
</Authorizing>
<NotAuthorized>
@if (context.User.Identity?.IsAuthenticated != true)
{
NavigationManager.NavigateTo("/login");
}
else
{
<p role="alert">You are not authorized to access this resource.</p>
}
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView>
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
</ChildContent>
<ErrorContent>
<ExceptionModal @ref="ExceptionModal"
Exception="@context"
ErrorBoundary="@ErrorBoundary"
OnRetry="() => ErrorBoundary?.Recover()"/>
</ErrorContent>
</ErrorBoundary>
@code {
private ErrorBoundary? ErrorBoundary { get; set; }
private ExceptionModal ExceptionModal { get; set; }
protected override async Task OnInitializedAsync()
{
await SteupDataService.Init();
}
}

View File

@@ -0,0 +1,6 @@
@using SteUp.Shared.Core.Interface.System
@inject IGenericSystemService GenericSystemService
<div class="app-version">
<span>@GenericSystemService.GetCurrentAppVersion()</span>
</div>

View File

@@ -0,0 +1,11 @@
.app-version{
width: 100%;
display: flex;
justify-content: center;
margin: 8px 0;
}
.app-version span{
font-size: smaller;
color: var(--mud-palette-gray-darker);
}

Some files were not shown because too many files have changed in this diff Show More