52 Commits

Author SHA1 Message Date
3b3841d7b6 Finish v2.2.2(26) 2025-12-30 17:41:03 +01:00
c8d3ec6eec Finish v2.2.2(26) 2025-12-30 17:41:02 +01:00
3218ade202 -> v2.2.2 (26) 2025-12-30 17:40:56 +01:00
ce86cba86c Fix downloadFile 2025-12-30 17:40:08 +01:00
37d66c90d2 Fix sync utenti 2025-12-29 13:45:02 +01:00
5c1d74e04d Finish v2.2.1(25) 2025-12-18 11:55:00 +01:00
394d0ace47 Finish v2.2.1(25) 2025-12-18 11:54:58 +01:00
99cd67fd5e -> v2.2.1 (25) 2025-12-18 11:54:49 +01:00
c336084152 Fix sync 2025-12-18 11:53:51 +01:00
74ac06b4c1 Finish v2.2.0(24) 2025-11-17 11:14:44 +01:00
70e68e59fb Finish v2.2.0(24) 2025-11-17 11:14:43 +01:00
032dd78c8c -> v2.2.0 (24) 2025-11-17 11:14:37 +01:00
e4b252f301 Migliorato caricamento clienti 2025-11-17 11:11:05 +01:00
a91e08f162 Aggiunta sync giornaliera delle commesse 2025-11-14 15:59:09 +01:00
3fd5410bf5 Aggiunta versione app a video 2025-11-14 12:40:17 +01:00
e338e7d253 Fix caricamenti in Modal Activity 2025-11-14 09:58:52 +01:00
d982aa9bf5 Finish v2.1.5(23) 2025-11-11 14:51:34 +01:00
39c34e7c7d Finish v2.1.5(23) 2025-11-11 14:51:33 +01:00
1f530bc130 -> v2.1.5 (23) 2025-11-11 14:51:25 +01:00
a4c2eee49d Valorizzato tipoAnag 2025-11-11 13:38:53 +01:00
70a34eef06 Finish v2.1.4(22) 2025-11-11 11:59:28 +01:00
c61ebe348c Finish v2.1.4(22) 2025-11-11 11:59:27 +01:00
e586279c6b -> v2.1.4 (22) 2025-11-11 11:59:22 +01:00
85e227a5cb Fix apple 2025-11-11 11:58:51 +01:00
71ce027fb8 Finish v2.1.4(21) 2025-11-11 11:32:26 +01:00
9318d7bd3f Finish v2.1.4(21) 2025-11-11 11:32:25 +01:00
3ae0a7f7d1 -> v2.1.4 (21) 2025-11-11 11:32:14 +01:00
2879008c20 Fix apple 2025-11-11 11:31:48 +01:00
0dfc0baa28 Finish v2.1.3(20) 2025-11-05 15:22:59 +01:00
b423ce8d16 Finish v2.1.3(20) 2025-11-05 15:22:57 +01:00
514f98a8a7 -> v2.1.3 (20) 2025-11-05 15:22:51 +01:00
a26f1a57cc Aggiunto caricamento file 2025-11-05 15:20:27 +01:00
f4b2e70881 Ripristinata cancellazione documenti 2025-11-05 15:06:34 +01:00
bb0bf1e496 Fix 2025-11-05 11:44:47 +01:00
d0f961b052 Aggiunta forzatura della sinc dopo 7 giorni 2025-11-04 12:06:10 +01:00
61ea1776b3 Finish v2.1.1(18) 2025-11-04 07:32:23 +01:00
8dcd61b697 Finish v2.1.1(18) 2025-11-04 07:32:23 +01:00
2480a6a60c -> v2.1.1 (18) 2025-11-04 07:32:12 +01:00
dd5f354b14 Fix caricamento post prima login 2025-11-04 07:31:15 +01:00
6a8414ff6c Finish v2.1.0(17) 2025-11-03 15:03:15 +01:00
b93f2f2d16 Finish v2.1.0(17) 2025-11-03 15:03:14 +01:00
a741d60e01 -> v2.1.0 (17) 2025-11-03 15:03:05 +01:00
5c1c9130ec Fix Apple 2025-11-03 15:02:08 +01:00
8a97506dfd Finish v2.1.0(16) 2025-10-30 13:45:06 +01:00
56c7d80c7c Finish v2.1.0(16) 2025-10-30 13:45:05 +01:00
3d231ac7c7 -> v2.1.0 (16) 2025-10-30 13:44:32 +01:00
5814243c2b Fix Apple 2025-10-30 13:43:24 +01:00
f36741b8de Finish v2.1.0(15) 2025-10-30 12:13:51 +01:00
38eaaa9db2 Finish v2.1.0(15) 2025-10-30 12:13:50 +01:00
bd15ab5106 -> v2.1.0 (15) 2025-10-30 12:13:43 +01:00
42004f82a1 Fix keySensitive commessa 2025-10-30 12:13:08 +01:00
cf6e11193e Finish v2.1.0(14) 2025-10-30 11:35:30 +01:00
33 changed files with 552 additions and 186 deletions

View File

@@ -0,0 +1,6 @@
namespace salesbook.Maui.Core.Interface;
public interface IFilePreviewService
{
Task Preview(string fileName, string filePath);
}

View File

@@ -1,9 +1,10 @@
using salesbook.Shared.Core.Dto;
using salesbook.Maui.Core.Interface;
using salesbook.Shared.Core.Dto;
using salesbook.Shared.Core.Interface;
namespace salesbook.Maui.Core.Services;
public class AttachedService : IAttachedService
public class AttachedService(IFilePreviewService filePreviewService) : IAttachedService
{
public async Task<AttachedDTO?> SelectImageFromCamera()
{
@@ -95,48 +96,34 @@ public class AttachedService : IAttachedService
};
}
private static async Task<string?> SaveToTempStorage(Stream file, string fileName)
public async Task<string> SaveToTempStorage(Stream file, string fileName, CancellationToken ct = default)
{
var cacheDirectory = FileSystem.CacheDirectory;
var targetDirectory = Path.Combine(cacheDirectory, "file");
ArgumentNullException.ThrowIfNull(file);
if (!Directory.Exists(targetDirectory)) Directory.CreateDirectory(targetDirectory);
if (file.CanSeek)
file.Position = 0;
var tempFilePath = Path.Combine(targetDirectory, fileName + ".temp");
var filePath = Path.Combine(targetDirectory, fileName);
fileName = Path.GetFileName(fileName);
if (File.Exists(filePath)) return filePath;
var dir = FileSystem.CacheDirectory;
var filePath = Path.Combine(dir, fileName);
try
{
await using var fileStream =
new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
await file.CopyToAsync(fileStream);
File.Move(tempFilePath, filePath);
}
catch (Exception e)
{
Console.WriteLine($"Errore durante il salvataggio dello stream: {e.Message}");
SentrySdk.CaptureException(e);
return null;
}
finally
{
if (File.Exists(tempFilePath)) File.Delete(tempFilePath);
}
await using var fileStream = File.Create(filePath);
await file.CopyToAsync(fileStream, ct);
return filePath;
}
public async Task OpenFile(Stream file, string fileName)
public Task OpenFile(string fileName, string filePath)
{
var filePath = await SaveToTempStorage(file, fileName);
if (filePath is null) return;
await Launcher.OpenAsync(new OpenFileRequest
#if IOS
return filePreviewService.Preview(fileName, filePath);
#else
return Launcher.OpenAsync(new OpenFileRequest
{
Title = "Apri file",
File = new ReadOnlyFile(filePath)
});
#endif
}
}

View File

@@ -90,14 +90,22 @@ public class ManageDataService(
public async Task<List<ContactDTO>> GetContact(WhereCondContact? whereCond, DateTime? lastSync)
{
List<AnagClie>? contactList;
List<PtbPros>? prospectList;
whereCond ??= new WhereCondContact();
// Ottengo liste locali
var contactList = await localDb.Get<AnagClie>(x =>
(whereCond.FlagStato != null && x.FlagStato == whereCond.FlagStato) ||
(whereCond.PartIva != null && x.PartIva == whereCond.PartIva) ||
(whereCond.PartIva == null && whereCond.FlagStato == null)
);
var prospectList = await localDb.Get<PtbPros>(x =>
(whereCond.PartIva != null && x.PartIva == whereCond.PartIva) ||
(whereCond.PartIva == null)
);
if (networkService.ConnectionAvailable)
{
var response = new UsersSyncResponseDTO();
var clienti = await integryApiService.RetrieveAnagClie(
new CRMAnagRequestDTO
{
@@ -109,10 +117,6 @@ public class ManageDataService(
}
);
response.AnagClie = clienti.AnagClie;
response.VtbDest = clienti.VtbDest;
response.VtbCliePersRif = clienti.VtbCliePersRif;
var prospect = await integryApiService.RetrieveProspect(
new CRMProspectRequestDTO
{
@@ -123,31 +127,54 @@ public class ManageDataService(
}
);
response.PtbPros = prospect.PtbPros;
response.PtbProsRif = prospect.PtbProsRif;
if (lastSync == null)
{
await InsertDbUsers(new UsersSyncResponseDTO
{
AnagClie = clienti.AnagClie,
VtbDest = clienti.VtbDest,
VtbCliePersRif = clienti.VtbCliePersRif,
PtbPros = prospect.PtbPros,
PtbProsRif = prospect.PtbProsRif
});
}
else
{
_ = UpdateDbUsers(new UsersSyncResponseDTO
{
AnagClie = clienti.AnagClie,
VtbDest = clienti.VtbDest,
VtbCliePersRif = clienti.VtbCliePersRif,
PtbPros = prospect.PtbPros,
PtbProsRif = prospect.PtbProsRif
});
}
_ = UpdateDbUsers(response);
if (lastSync != null)
{
contactList = MergeLists(
contactList,
clienti.AnagClie,
x => x.CodAnag
);
contactList = clienti.AnagClie;
prospectList = prospect.PtbPros;
}
else
{
contactList = await localDb.Get<AnagClie>(x =>
(whereCond.FlagStato != null && x.FlagStato.Equals(whereCond.FlagStato)) ||
(whereCond.PartIva != null && x.PartIva.Equals(whereCond.PartIva)) ||
(whereCond.PartIva == null && whereCond.FlagStato == null)
);
prospectList = await localDb.Get<PtbPros>(x =>
(whereCond.PartIva != null && x.PartIva.Equals(whereCond.PartIva)) ||
(whereCond.PartIva == null)
);
prospectList = MergeLists(
prospectList,
prospect.PtbPros,
x => x.CodPpro
);
}
else
{
contactList = clienti.AnagClie;
prospectList = prospect.PtbPros;
}
}
// Mappa i contatti
var contactMapper = mapper.Map<List<ContactDTO>>(contactList);
// Mappa i prospects
// Mappa i prospect
var prospectMapper = mapper.Map<List<ContactDTO>>(prospectList);
contactMapper.AddRange(prospectMapper);
@@ -155,6 +182,23 @@ public class ManageDataService(
return contactMapper;
}
private static List<T>? MergeLists<T, TKey>(List<T>? localList, List<T>? apiList, Func<T, TKey> keySelector)
{
if (apiList == null && localList != null) return localList;
if (apiList != null && localList == null) return apiList;
if (apiList == null && localList == null) return null;
var dictionary = localList!.ToDictionary(keySelector);
foreach (var apiItem in apiList)
{
var key = keySelector(apiItem);
dictionary[key] = apiItem;
}
return dictionary.Values.ToList();
}
public async Task<ContactDTO?> GetSpecificContact(string codAnag, bool isContact)
{
if (isContact)
@@ -175,9 +219,7 @@ public class ManageDataService(
public async Task<List<ActivityDTO>> GetActivityTryLocalDb(WhereCondActivity whereCond)
{
List<StbActivity>? activities;
activities = await localDb.Get<StbActivity>(x =>
var activities = await localDb.Get<StbActivity>(x =>
(whereCond.ActivityId != null && x.ActivityId != null && whereCond.ActivityId.Equals(x.ActivityId)) ||
(whereCond.Start != null && whereCond.End != null && x.EffectiveTime == null &&
x.EstimatedTime >= whereCond.Start && x.EstimatedTime <= whereCond.End) ||
@@ -198,6 +240,7 @@ public class ManageDataService(
_ = UpdateDb(activities);
}
else return [];
return await MapActivity(activities);
}
@@ -219,16 +262,7 @@ public class ManageDataService(
_ = UpdateDb(activities);
}
else
{
activities = await localDb.Get<StbActivity>(x =>
(whereCond.ActivityId != null && x.ActivityId != null && whereCond.ActivityId.Equals(x.ActivityId)) ||
(whereCond.Start != null && whereCond.End != null && x.EffectiveTime == null &&
x.EstimatedTime >= whereCond.Start && x.EstimatedTime <= whereCond.End) ||
(x.EffectiveTime >= whereCond.Start && x.EffectiveTime <= whereCond.End) ||
(whereCond.ActivityId == null && (whereCond.Start == null || whereCond.End == null))
);
}
else return await GetActivityTryLocalDb(whereCond);
return await MapActivity(activities);
}
@@ -261,7 +295,8 @@ public class ManageDataService(
var returnDto = activities
.Select(activity =>
{
if (activity.CodJcom is "0000" && userSession.ProfileDb != null && userSession.ProfileDb.Equals("smetar", StringComparison.OrdinalIgnoreCase))
if (activity.CodJcom is "0000" && userSession.ProfileDb != null &&
userSession.ProfileDb.Equals("smetar", StringComparison.OrdinalIgnoreCase))
{
activity.CodJcom = null;
}
@@ -273,8 +308,7 @@ public class ManageDataService(
var minuteBefore = activity.EstimatedTime.Value - activity.AlarmTime.Value;
dto.MinuteBefore = (int)Math.Abs(minuteBefore.TotalMinutes);
dto.NotificationDate = dto.MinuteBefore == 0 ?
activity.EstimatedTime : activity.AlarmTime;
dto.NotificationDate = dto.MinuteBefore == 0 ? activity.EstimatedTime : activity.AlarmTime;
}
if (activity.CodJcom != null)
@@ -291,7 +325,7 @@ public class ManageDataService(
string? ragSoc;
if (distinctUser != null && (distinctUser.TryGetValue(activity.CodAnag, out ragSoc) ||
distinctUser.TryGetValue(activity.CodAnag, out ragSoc)))
distinctUser.TryGetValue(activity.CodAnag, out ragSoc)))
{
dto.Cliente = ragSoc;
}
@@ -305,6 +339,24 @@ public class ManageDataService(
return returnDto;
}
private async Task InsertDbUsers(UsersSyncResponseDTO response)
{
if (response.AnagClie != null)
{
await localDb.InsertAll(response.AnagClie);
if (response.VtbDest != null) await localDb.InsertAll(response.VtbDest);
if (response.VtbCliePersRif != null) await localDb.InsertAll(response.VtbCliePersRif);
}
if (response.PtbPros != null)
{
await localDb.InsertAll(response.PtbPros);
if (response.PtbProsRif != null) await localDb.InsertAll(response.PtbProsRif);
}
}
private Task UpdateDbUsers(UsersSyncResponseDTO response)
{
return Task.Run(async () =>

View File

@@ -0,0 +1,8 @@
using salesbook.Shared.Core.Interface.System;
namespace salesbook.Maui.Core.System;
public class GenericSystemService : IGenericSystemService
{
public string GetCurrentAppVersion() => AppInfo.VersionString;
}

View File

@@ -5,8 +5,11 @@ using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.Logging;
using MudBlazor.Services;
using MudExtensions.Services;
using salesbook.Maui.Core;
using salesbook.Maui.Core.Interface;
using salesbook.Maui.Core.RestClient.IntegryApi;
using salesbook.Maui.Core.Services;
using salesbook.Maui.Core.System;
using salesbook.Maui.Core.System.Network;
using salesbook.Maui.Core.System.Notification;
using salesbook.Maui.Core.System.Notification.Push;
@@ -16,6 +19,7 @@ using salesbook.Shared.Core.Dto.PageState;
using salesbook.Shared.Core.Helpers;
using salesbook.Shared.Core.Interface;
using salesbook.Shared.Core.Interface.IntegryApi;
using salesbook.Shared.Core.Interface.System;
using salesbook.Shared.Core.Interface.System.Network;
using salesbook.Shared.Core.Interface.System.Notification;
using salesbook.Shared.Core.Messages.Activity.Copy;
@@ -102,7 +106,9 @@ namespace salesbook.Maui
builder.Services.AddSingleton<IFormFactor, FormFactor>();
builder.Services.AddSingleton<IAttachedService, AttachedService>();
builder.Services.AddSingleton<INetworkService, NetworkService>();
builder.Services.AddSingleton<IGenericSystemService, GenericSystemService>();
builder.Services.AddSingleton<LocalDbService>();
builder.Services.AddSingleton<IFilePreviewService, FilePreviewService>();
_ = typeof(System.Runtime.InteropServices.SafeHandle);
_ = typeof(System.IO.FileStream);

View File

@@ -0,0 +1,11 @@
using salesbook.Maui.Core.Interface;
namespace salesbook.Maui.Core;
public class FilePreviewService :IFilePreviewService
{
public Task Preview(string fileName, string filePath)
{
throw new NotImplementedException();
}
}

View File

@@ -0,0 +1,24 @@
using QuickLook;
using salesbook.Maui.Core.Interface;
using salesbook.Maui.Helpers;
using UIKit;
namespace salesbook.Maui.Core;
public class FilePreviewService : IFilePreviewService
{
public Task Preview(string fileName, string filePath)
{
var currentController = UIApplication.SharedApplication.KeyWindow?.RootViewController;
while (currentController?.PresentedViewController != null)
currentController = currentController.PresentedViewController;
var currentView = currentController?.View;
var qLPreview = new QLPreviewController();
var item = new QlPreviewItemBundle(fileName, filePath);
qLPreview.DataSource = new PreviewControllerDs(item);
currentController?.PresentViewController(qLPreview, true, null);
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,16 @@
using QuickLook;
namespace salesbook.Maui.Helpers;
public class PreviewControllerDs(QLPreviewItem item) : QLPreviewControllerDataSource
{
public override nint PreviewItemCount(QLPreviewController controller)
{
return 1;
}
public override IQLPreviewItem GetPreviewItem(QLPreviewController controller, nint index)
{
return item;
}
}

View File

@@ -0,0 +1,19 @@
using Foundation;
using QuickLook;
namespace salesbook.Maui.Helpers;
public class QlPreviewItemBundle(string fileName, string filePath) : QLPreviewItem
{
public override string PreviewItemTitle => fileName;
public override NSUrl PreviewItemUrl
{
get
{
var documents = NSBundle.MainBundle.BundlePath;
var lib = Path.Combine(documents, filePath);
var url = NSUrl.FromFilename(lib);
return url;
}
}
}

View File

@@ -0,0 +1,12 @@
using Foundation;
using QuickLook;
namespace salesbook.Maui.Helpers;
public class QlPreviewItemFileSystem(string fileName, string filePath) : QLPreviewItem
{
public override string PreviewItemTitle => fileName;
public override NSUrl PreviewItemUrl => NSUrl.FromString(filePath);
}

View File

@@ -51,6 +51,9 @@
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Permette all'app di salvare file o immagini nella tua libreria fotografica se necessario.</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Alcune librerie di sistema potrebbero accedere al Bluetooth. Lapp non utilizza direttamente il Bluetooth.</string>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>

View File

@@ -2,47 +2,108 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Elenco dei dati raccolti -->
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeUserID</string>
<key>NSPrivacyCollectedDataTypeLinkedToUser</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
</dict>
</array>
<!-- API che accedono a dati sensibili -->
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPITypeCamera</string>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CAMeraCapture</string>
<string>CA92.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPITypePhotoLibrary</string>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>PHOTOLibraryAdd</string>
<string>PHOTOLibraryRead</string>
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
</array>
<!-- Versione e autore -->
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCustomPurposeDescription</key>
<dict/>
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeCrashData</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false />
<key>NSPrivacyCollectedDataTypeTracking</key>
<false />
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypePerformanceData</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false />
<key>NSPrivacyCollectedDataTypeTracking</key>
<false />
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeOtherDiagnosticData</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false />
<key>NSPrivacyCollectedDataTypeTracking</key>
<false />
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypePreciseLocation</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false />
<key>NSPrivacyCollectedDataTypeTracking</key>
<false />
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeCoarseLocation</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false />
<key>NSPrivacyCollectedDataTypeTracking</key>
<false />
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypePhotosorVideos</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false />
<key>NSPrivacyCollectedDataTypeTracking</key>
<false />
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
</dict>
</plist>

View File

@@ -29,8 +29,8 @@
<ApplicationId>it.integry.salesbook</ApplicationId>
<!-- Versions -->
<ApplicationDisplayVersion>2.1.0</ApplicationDisplayVersion>
<ApplicationVersion>14</ApplicationVersion>
<ApplicationDisplayVersion>2.2.2</ApplicationDisplayVersion>
<ApplicationVersion>26</ApplicationVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
<!--<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
@@ -120,6 +120,7 @@
<PublishTrimmed>true</PublishTrimmed>
<PublishAot>true</PublishAot>
<MonoAotMode>Hybrid</MonoAotMode>
<MtouchLink>None</MtouchLink>
</PropertyGroup>
<ItemGroup>
@@ -155,7 +156,7 @@
<ItemGroup>
<PackageReference Include="CommunityToolkit.Maui" Version="12.2.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="IntegryApiClient.MAUI" Version="1.2.2" />
<PackageReference Include="IntegryApiClient.MAUI" Version="1.2.3" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.10" />
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.120" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="9.0.120" />

View File

@@ -492,6 +492,8 @@
// Selezione giorno in settimana
private async Task SelezionaData(DateTime day)
{
if (IsLoading) return;
SelectedDate = day;
var cacheInternalMonth = _internalMonth;
@@ -513,6 +515,8 @@
// Selezione giorno dal mese (chiude la vista mese!)
private async Task SelezionaDataDalMese(DateTime day)
{
if (IsLoading) return;
SelectedDate = day;
SliderAnimation = "collapse-animation";
Expanded = false;

View File

@@ -121,6 +121,7 @@
background: var(--light-card-background);
border-radius: 16px;
overflow: clip;
min-height: 45px;
margin-bottom: 1rem;
}

View File

@@ -15,12 +15,30 @@
@inject PreloadService PreloadService
@inject IMessenger Messenger
<SpinnerLayout FullScreen="true" />
<SpinnerLayout FullScreen="true"/>
@code
{
protected override async Task OnInitializedAsync()
{
var lastSyncDate = LocalStorage.Get<DateTime>("last-sync");
var syncAllData = lastSyncDate.Equals(DateTime.MinValue) || (DateTime.Now - lastSyncDate).TotalDays >= 7;
var syncCodJcom = lastSyncDate.Day != DateTime.Now.Day;
if (!FormFactor.IsWeb() && NetworkService.ConnectionAvailable && syncAllData)
{
var returnPath = System.Web.HttpUtility.UrlEncode("/");
NavigationManager.NavigateTo($"/sync?path={returnPath}");
return;
}
if (syncCodJcom && !syncAllData)
{
var returnPath = System.Web.HttpUtility.UrlEncode("/");
NavigationManager.NavigateTo($"/sync/{DateTime.Today:yyyy-MM-dd}?path={returnPath}");
return;
}
NetworkService.ConnectionAvailable = NetworkService.IsNetworkAvailable();
await LoadNotification();
@@ -35,14 +53,6 @@
Console.WriteLine($"Firebase init: {e.Message}");
}
var lastSyncDate = LocalStorage.Get<DateTime>("last-sync");
if (!FormFactor.IsWeb() && NetworkService.ConnectionAvailable && lastSyncDate.Equals(DateTime.MinValue))
{
NavigationManager.NavigateTo("/sync");
return;
}
_ = StartSyncUser();
NavigationManager.NavigateTo("/Calendar");
}
@@ -60,9 +70,6 @@
private Task StartSyncUser()
{
return Task.Run(() =>
{
_ = PreloadService.PreloadUsersAsync();
});
return Task.Run(() => { _ = PreloadService.PreloadUsersAsync(); });
}
}

View File

@@ -1,8 +1,10 @@
@page "/login"
@using salesbook.Shared.Components.Layout.Spinner
@using salesbook.Shared.Core.Interface.System
@using salesbook.Shared.Core.Services
@inject IUserAccountService UserAccountService
@inject AppAuthenticationStateProvider AuthenticationStateProvider
@inject IGenericSystemService GenericSystemService
@if (Spinner)
{
@@ -34,7 +36,7 @@ else
</div>
<div class="my-4 login-footer">
<span>Powered by</span>
<span>@($"v{GenericSystemService.GetCurrentAppVersion()} | Powered by")</span>
<img src="_content/salesbook.Shared/images/logoIntegry.svg" class="img-fluid" alt="Integry">
</div>
</div>

View File

@@ -1,13 +1,16 @@
@page "/PersonalInfo"
@attribute [Authorize]
@using salesbook.Shared.Components.Layout
@using salesbook.Shared.Components.SingleElements
@using salesbook.Shared.Core.Authorization.Enum
@using salesbook.Shared.Core.Dto.PageState
@using salesbook.Shared.Core.Interface
@using salesbook.Shared.Core.Interface.System.Network
@using salesbook.Shared.Core.Services
@inject AppAuthenticationStateProvider AuthenticationStateProvider
@inject INetworkService NetworkService
@inject IFormFactor FormFactor
@inject UserListState UserState
<HeaderLayout BackTo="Indietro" Back="true" BackOnTop="true" Title="Profilo" ShowProfile="false"/>
@@ -16,7 +19,8 @@
<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">
<MudAvatar Style="height: 70px; width: 70px; font-size: 2rem; font-weight: bold"
Color="Color.Secondary">
@UtilityString.ExtractInitials(UserSession.User.Fullname)
</MudAvatar>
@@ -24,7 +28,8 @@
<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>
<span
class="info-section">@(((KeyGroupEnum)UserSession.User.KeyGroup).ConvertToHumanReadable())</span>
}
</div>
</div>
@@ -85,7 +90,7 @@
FullWidth="true"
StartIcon="@Icons.Material.Outlined.Sync"
Size="Size.Medium"
OnClick="() => UpdateDb()"
OnClick="@(() => UpdateDb())"
Variant="Variant.Outlined">
Sincronizza
</MudButton>
@@ -113,6 +118,8 @@
</MudButton>
</div>
</div>
<AppVersion/>
}
@code {
@@ -149,17 +156,11 @@
private void UpdateDb(bool withData = false)
{
var absoluteUri = NavigationManager.ToAbsoluteUri(NavigationManager.Uri);
var pathAndQuery = absoluteUri.Segments.Length > 1 ? absoluteUri.PathAndQuery : null;
LocalStorage.Remove("last-user-sync");
UserState.IsLoaded = false;
UserState.IsLoading = false;
string path;
if (withData)
path = pathAndQuery == null ? $"/sync/{DateTime.Today:yyyy-MM-dd}" : $"/sync/{DateTime.Today:yyyy-MM-dd}?path=" + System.Web.HttpUtility.UrlEncode(pathAndQuery);
else
path = pathAndQuery == null ? "/sync" : "/sync?path=" + System.Web.HttpUtility.UrlEncode(pathAndQuery);
NavigationManager.NavigateTo(path, replace: true);
NavigationManager.NavigateTo(withData ? $"/sync/{DateTime.Today:yyyy-MM-dd}" : "/sync", replace: true);
}
}

View File

@@ -1,24 +1,31 @@
@page "/sync"
@page "/sync/{DateFilter}"
@using salesbook.Shared.Components.Layout.Spinner
@using salesbook.Shared.Components.SingleElements
@using salesbook.Shared.Core.Interface
@inject ISyncDbService syncDb
@inject IManageDataService manageData
@using salesbook.Shared.Core.Services
@inject ISyncDbService SyncDb
@inject IManageDataService ManageData
@inject PreloadService PreloadService
<SyncSpinner Elements="@Elements"/>
<AppVersion/>
@code {
[Parameter] public string? DateFilter { get; set; }
private Dictionary<string, bool> Elements { get; set; } = new();
private bool _hasStarted = false;
private int _completedCount = 0;
private bool _hasStarted;
private int _completedCount;
protected override void OnInitialized()
{
Elements["Commesse"] = false;
Elements["Impostazioni"] = false;
if (DateFilter is null)
Elements["Impostazioni"] = false;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
@@ -28,9 +35,7 @@
_hasStarted = true;
if (DateFilter is null)
{
await manageData.ClearDb();
}
await ManageData.ClearDb();
await Task.WhenAll(
RunAndTrack(SetCommesse),
@@ -52,13 +57,18 @@
var originalPath = pathQuery["path"] ?? null;
var path = originalPath ?? "/Calendar";
if (path.Equals("/Calendar") && DateFilter is null)
{
_ = Task.Run(() => { _ = PreloadService.PreloadUsersAsync(); });
}
NavigationManager.NavigateTo(path, replace: true);
}
}
private async Task SetCommesse()
{
await Task.Run(async () => { await syncDb.GetAndSaveCommesse(DateFilter); });
await Task.Run(async () => { await SyncDb.GetAndSaveCommesse(DateFilter); });
Elements["Commesse"] = true;
StateHasChanged();
@@ -66,10 +76,13 @@
private async Task SetSettings()
{
await Task.Run(async () => { await syncDb.GetAndSaveSettings(DateFilter); });
if (DateFilter is null)
{
await Task.Run(async () => { await SyncDb.GetAndSaveSettings(DateFilter); });
Elements["Impostazioni"] = true;
StateHasChanged();
Elements["Impostazioni"] = true;
StateHasChanged();
}
}
}

View File

@@ -23,7 +23,7 @@
OnSave="() => OpenUserForm(Anag)"
Back="true"
BackOnTop="true"
Title=""
Title="@Anag.CodContact"
ShowProfile="false"/>
@if (IsLoading)
@@ -111,7 +111,7 @@ else
<label class="tab-trigger" for="tab2" @onclick="() => SwitchTab(1)">Commesse</label>
</li>
<li class="tab-item">
<label class="tab-trigger" for="tab3" @onclick="() => SwitchTab(2)">Attivit<EFBFBD></label>
<label class="tab-trigger" for="tab3" @onclick="() => SwitchTab(2)">Attività</label>
</li>
</ul>
</div>
@@ -219,7 +219,7 @@ else
}
</div>
<!-- Tab Attivit<EFBFBD> -->
<!-- Tab Attività -->
<div class="tab-content" style="display: @(ActiveTab == 2 ? "block" : "none")">
@if (ActivityIsLoading)
{
@@ -227,7 +227,7 @@ else
}
else if (ActivityList?.Count == 0)
{
<NoDataAvailable Text="Nessuna attivit<EFBFBD> presente"/>
<NoDataAvailable Text="Nessuna attività presente"/>
}
else if (ActivityList != null)
{
@@ -274,9 +274,9 @@ else
</div>
</div>
<MudScrollToTop Selector="#topPage" VisibleCssClass="visible absolute" TopOffset="100" HiddenCssClass="invisible">
<MudFab Size="Size.Small" Color="Color.Primary" StartIcon="@Icons.Material.Rounded.KeyboardArrowUp"/>
</MudScrollToTop>
@* <MudScrollToTop Selector="#topPage" VisibleCssClass="visible absolute" TopOffset="100" HiddenCssClass="invisible"> *@
@* <MudFab Size="Size.Small" Color="Color.Primary" StartIcon="@Icons.Material.Rounded.KeyboardArrowUp"/> *@
@* </MudScrollToTop> *@
</div>
</div>
}
@@ -309,7 +309,7 @@ else
private string _searchTermCommesse = string.Empty;
private List<JtbComt> _filteredCommesse = [];
// Paginazione e filtri per ATTIVIT<EFBFBD>
// Paginazione e filtri per attività
private int _currentPageActivity = 1;
private int _selectedPageSizeActivity = 5;
private string _searchTermActivity = string.Empty;
@@ -381,7 +381,7 @@ else
#endregion
#region Properties per Attivit<EFBFBD>
#region Properties per Attività
private int CurrentPageActivityIndex
{
@@ -445,7 +445,7 @@ else
{
_loadingCts = new CancellationTokenSource();
if (UserState.CodUser?.Equals(CodContact) == true)
if (UserState.CodUser != null && UserState.CodUser.Equals(CodContact))
{
LoadDataFromSession();
}

View File

@@ -170,6 +170,7 @@
var matchesText =
(!string.IsNullOrEmpty(user.RagSoc) && user.RagSoc.Contains(filter, StringComparison.OrdinalIgnoreCase)) ||
(!string.IsNullOrEmpty(user.CodContact) && user.CodContact.Contains(filter, StringComparison.OrdinalIgnoreCase)) ||
(!string.IsNullOrEmpty(user.Indirizzo) && user.Indirizzo.Contains(filter, StringComparison.OrdinalIgnoreCase)) ||
(!string.IsNullOrEmpty(user.Telefono) && user.Telefono.Contains(filter, StringComparison.OrdinalIgnoreCase)) ||
(!string.IsNullOrEmpty(user.EMail) && user.EMail.Contains(filter, StringComparison.OrdinalIgnoreCase)) ||

View File

@@ -0,0 +1,6 @@
@using salesbook.Shared.Core.Interface.System
@inject IGenericSystemService GenericSystemService
<div class="app-version">
<span>@($"v{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);
}

View File

@@ -1,3 +1,4 @@
@using salesbook.Shared.Components.Layout.Spinner
@using salesbook.Shared.Core.Dto
@using salesbook.Shared.Core.Interface
@using salesbook.Shared.Core.Interface.IntegryApi
@@ -34,12 +35,24 @@
</div>
</div>
<OverlayLayout Visible="VisibleOverlay" />
@code {
[Parameter] public CRMAttachedResponseDTO Attached { get; set; } = new();
private bool VisibleOverlay { get; set; }
private async Task OpenAttached()
{
var bytes = await IntegryApiService.DownloadFileFromRefUuid(Attached.RefUuid, Attached.FileName);
await AttachedService.OpenFile(bytes, Attached.FileName);
VisibleOverlay = true;
StateHasChanged();
await using var file = await IntegryApiService.DownloadFileFromRefUuid(Attached.RefUuid, Attached.FileName);
var path = await AttachedService.SaveToTempStorage(file, Attached.FileName);
VisibleOverlay = false;
StateHasChanged();
await AttachedService.OpenFile(Attached.FileName, path);
}
}

View File

@@ -2,6 +2,7 @@
@using CommunityToolkit.Mvvm.Messaging
@using salesbook.Shared.Components.Layout
@using salesbook.Shared.Components.Layout.Overlay
@using salesbook.Shared.Components.Layout.Spinner
@using salesbook.Shared.Components.SingleElements.BottomSheet
@using salesbook.Shared.Core.Dto
@using salesbook.Shared.Core.Dto.Activity
@@ -214,29 +215,38 @@
@if (item.p.Type == AttachedDTO.TypeAttached.Position)
{
<MudChip T="string" Icon="@Icons.Material.Rounded.LocationOn" Color="Color.Success"
OnClick="() => OpenPosition(item.p)" OnClose="() => OnRemoveAttached(item.index)">
OnClick="@(() => OpenPosition(item.p))"
OnClose="@(() => OnRemoveAttached(item.index))">
@item.p.Description
</MudChip>
}
else
{
<MudChip T="string" Color="Color.Default" OnClick="() => OpenAttached(item.p)"
OnClose="() => OnRemoveAttached(item.index)">
<MudChip T="string" Color="Color.Default" OnClick="@(() => OpenAttached(item.p))"
OnClose="@(() => OnRemoveAttached(item.index))">
@item.p.Name
</MudChip>
}
}
}
@if (ActivityFileList != null)
@if (!IsLoading)
{
foreach (var file in ActivityFileList)
if (ActivityFileList != null)
{
<MudChip T="string" OnClick="() => OpenAttached(file.Id, file.FileName)" Color="Color.Default">
@file.FileName
</MudChip>
foreach (var file in ActivityFileList)
{
<MudChip T="string" OnClick="@(() => OpenAttached(file.FileName))"
OnClose="@(() => DeleteAttach(file))" Color="Color.Default">
@file.FileName
</MudChip>
}
}
}
else
{
<MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="my-7"/>
}
</div>
@if (!IsView)
@@ -295,6 +305,8 @@
<SaveOverlay VisibleOverlay="VisibleOverlay" SuccessAnimation="SuccessAnimation"/>
<OverlayLayout Visible="VisibleLoadingOverlay"/>
<SelectEsito @bind-IsSheetVisible="OpenEsito" @bind-ActivityModel="ActivityModel"
@bind-ActivityModel:after="OnAfterChangeEsito"/>
@@ -318,12 +330,14 @@
private List<ActivityFileDto>? ActivityFileList { get; set; }
private bool IsNew { get; set; }
private bool IsLoading { get; set; }
private bool IsView => !NetworkService.ConnectionAvailable;
private string? LabelSave { get; set; }
//Overlay for save
//Overlay
private bool VisibleOverlay { get; set; }
private bool VisibleLoadingOverlay { get; set; }
private bool SuccessAnimation { get; set; }
private bool OpenEsito { get; set; }
@@ -443,11 +457,17 @@
{
return Task.Run(async () =>
{
IsLoading = true;
await InvokeAsync(StateHasChanged);
SelectedComessa = ActivityModel.Commessa;
Users = await ManageData.GetTable<StbUser>();
if (!ActivityModel.UserName.IsNullOrEmpty())
{
SelectedUser = Users.FindLast(x => x.UserName.Equals(ActivityModel.UserName));
await InvokeAsync(StateHasChanged);
}
if (!IsNew && Id != null)
ActivityFileList = await IntegryApiService.GetActivityFile(Id);
@@ -456,6 +476,7 @@
Clienti = await ManageData.GetClienti(new WhereCondContact { FlagStato = "A" });
Pros = await ManageData.GetProspect();
IsLoading = false;
await InvokeAsync(StateHasChanged);
});
}
@@ -479,8 +500,8 @@
if (ActivityModel.CodAnag == null)
{
Commesse = await ManageData.GetTable<JtbComt>(x =>
x.CodJcom.Contains(searchValue) ||
x.Descrizione.Contains(searchValue)
x.CodJcom.ToUpper().Contains(searchValue.ToUpper()) ||
x.Descrizione.ToUpper().Contains(searchValue.ToUpper())
);
}
else
@@ -544,11 +565,11 @@
var results = new List<string>();
results.AddRange(Clienti
.Where(x => x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase))
.Where(x => (x.CodAnag != null && x.CodAnag.Contains(value, StringComparison.OrdinalIgnoreCase)) || x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase))
.Select(x => $"{x.CodAnag} - {x.RagSoc}"));
results.AddRange(Pros
.Where(x => x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase))
.Where(x => (x.CodPpro != null && x.CodPpro.Contains(value, StringComparison.OrdinalIgnoreCase)) || x.RagSoc.Contains(value, StringComparison.OrdinalIgnoreCase))
.Select(x => $"{x.CodPpro} - {x.RagSoc}"));
return Task.FromResult<IEnumerable<string>?>(results);
@@ -564,6 +585,9 @@
{
ActivityModel.CodAnag = parts[0];
ActivityModel.Cliente = parts[1];
var isCliente = Clienti.FirstOrDefault(x => x.CodAnag != null && x.CodAnag.Equals(ActivityModel.CodAnag));
ActivityModel.TipoAnag = isCliente == null ? "P" : "C";
}
OnAfterChangeValue();
@@ -581,6 +605,7 @@
if (com.CodAnag != null)
{
ActivityModel.CodAnag = com.CodAnag;
ActivityModel.TipoAnag = com.TipoAnag;
ActivityModel.Cliente = Clienti
.Where(x => x.CodAnag != null && x.CodAnag.Equals(com.CodAnag))
.Select(x => x.RagSoc)
@@ -593,6 +618,7 @@
{
ActivityModel.CodAnag = null;
ActivityModel.Cliente = null;
ActivityModel.TipoAnag = null;
}
}
else
@@ -601,6 +627,7 @@
ActivityModel.Commessa = null;
ActivityModel.CodAnag = null;
ActivityModel.Cliente = null;
ActivityModel.TipoAnag = null;
}
OnAfterChangeValue();
@@ -747,15 +774,29 @@
StateHasChanged();
}
private async Task OpenAttached(string idAttached, string fileName)
private async Task OpenAttached(string fileName)
{
try
{
var bytes = await IntegryApiService.DownloadFile(ActivityModel.ActivityId!, fileName);
await AttachedService.OpenFile(bytes, fileName);
VisibleOverlay = true;
StateHasChanged();
await using var file = await IntegryApiService.DownloadFile(ActivityModel.ActivityId!, fileName);
var path = await AttachedService.SaveToTempStorage(file, fileName);
VisibleOverlay = false;
StateHasChanged();
await AttachedService.OpenFile(fileName, path);
}
catch (Exception ex)
{
if (VisibleOverlay)
{
VisibleOverlay = false;
StateHasChanged();
}
Snackbar.Clear();
Snackbar.Add("Impossibile aprire il file", Severity.Error);
Console.WriteLine($"Errore durante l'apertura del file: {ex.Message}");
@@ -766,7 +807,15 @@
{
if (attached is { FileContent: not null, MimeType: not null })
{
await AttachedService.OpenFile(attached.FileContent!, attached.Name);
VisibleOverlay = true;
StateHasChanged();
var path = await AttachedService.SaveToTempStorage(attached.FileContent!, attached.Name);
VisibleOverlay = false;
StateHasChanged();
await AttachedService.OpenFile(attached.Name, path);
}
else
{
@@ -775,6 +824,33 @@
}
}
private async Task DeleteAttach(ActivityFileDto file)
{
Snackbar.Clear();
if (ActivityFileList == null) return;
try
{
ActivityFileList.Remove(file);
StateHasChanged();
await IntegryApiService.DeleteFile(ActivityModel.ActivityId!, file.FileName);
}
catch (Exception ex)
{
ActivityFileList.Add(file);
StateHasChanged();
Snackbar.Add("Impossibile eliminare il file", Severity.Error);
Console.WriteLine($"Impossibile eliminare il file: {ex.Message}");
}
finally
{
Snackbar.Add($"{file.FileName} eliminato con successo", Severity.Info);
}
}
private void OpenPosition(AttachedDTO attached)
{
if (attached is { Lat: not null, Lng: not null })

View File

@@ -3,6 +3,11 @@
public enum KeyGroupEnum
{
UtenteAziendale = 2,
Cliente = 3,
Agenti = 5,
Tecnico = 22
AmministratoreAziendale = 9,
Tecnico = 22,
ResponsabileDiReparto = 23,
ResponsabileAmministrativo = 29,
Programmatore = 30
}

View File

@@ -11,6 +11,11 @@ public static class KeyGroupHelper
KeyGroupEnum.Agenti => "Agenti",
KeyGroupEnum.Tecnico => "Tecnico",
KeyGroupEnum.UtenteAziendale => "Utente Aziendale",
KeyGroupEnum.AmministratoreAziendale => "Amministratore Aziendale",
KeyGroupEnum.ResponsabileDiReparto => "Responsabile Di Reparto",
KeyGroupEnum.Programmatore => "Programmatore",
KeyGroupEnum.Cliente => "Cliente",
KeyGroupEnum.ResponsabileAmministrativo => "Responsabile Amministrativo",
_ => throw new ArgumentOutOfRangeException(nameof(keyGroup), keyGroup, null)
};
}

View File

@@ -8,5 +8,7 @@ public interface IAttachedService
Task<AttachedDTO?> SelectImageFromGallery();
Task<AttachedDTO?> SelectFile();
Task<AttachedDTO?> SelectPosition();
Task OpenFile(Stream file, string fileName);
Task<string> SaveToTempStorage(Stream file, string fileName, CancellationToken ct = default);
Task OpenFile(string fileName, string filePath);
}

View File

@@ -0,0 +1,6 @@
namespace salesbook.Shared.Core.Interface.System;
public interface IGenericSystemService
{
string GetCurrentAppVersion();
}

View File

@@ -160,7 +160,7 @@ public class IntegryApiService(IIntegryApiRestClient integryApiRestClient, IUser
}
public Task<Stream> DownloadFile(string activityId, string fileName) =>
integryApiRestClient.Download($"downloadStbFileAttachment/{activityId}/{fileName}")!;
integryApiRestClient.Download($"downloadStbActivityFileAttachment/{activityId}/{fileName}")!;
public Task<Stream> DownloadFileFromRefUuid(string refUuid, string fileName)
{

View File

@@ -1,4 +1,6 @@
using salesbook.Shared.Core.Dto;
using IntegryApiClient.Core.Domain.Abstraction.Contracts.Storage;
using Java.Sql;
using salesbook.Shared.Core.Dto;
using salesbook.Shared.Core.Dto.Contact;
using salesbook.Shared.Core.Dto.PageState;
using salesbook.Shared.Core.Dto.Users;
@@ -6,7 +8,7 @@ using salesbook.Shared.Core.Interface;
namespace salesbook.Shared.Core.Services;
public class PreloadService(IManageDataService manageData, UserListState userState)
public class PreloadService(IManageDataService manageData, ILocalStorage localStorage, UserListState userState)
{
public async Task PreloadUsersAsync()
{
@@ -15,7 +17,10 @@ public class PreloadService(IManageDataService manageData, UserListState userSta
userState.IsLoading = true;
var users = await manageData.GetContact(new WhereCondContact { FlagStato = "A" });
DateTime? lastSync = localStorage.Get<DateTime>("last-user-sync");
lastSync = lastSync.Equals(DateTime.MinValue) ? null : lastSync;
var users = await manageData.GetContact(new WhereCondContact { FlagStato = "A" }, lastSync);
var sorted = users
.Where(u => !string.IsNullOrWhiteSpace(u.RagSoc))
@@ -27,6 +32,8 @@ public class PreloadService(IManageDataService manageData, UserListState userSta
userState.FilteredGroupedUserList = userState.GroupedUserList;
userState.AllUsers = users;
localStorage.Set("last-user-sync", DateTime.Now);
userState.NotifyUsersLoaded();
}

View File

@@ -24,7 +24,7 @@
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="CodeBeam.MudBlazor.Extensions" Version="8.2.4" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="IntegryApiClient.Core" Version="1.2.2" />
<PackageReference Include="IntegryApiClient.Core" Version="1.2.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.10" />
<PackageReference Include="Microsoft.Maui.Essentials" Version="9.0.120" />
<PackageReference Include="SourceGear.sqlite3" Version="3.50.4.2" />

View File

@@ -16,7 +16,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="IntegryApiClient.Blazor" Version="1.2.2" />
<PackageReference Include="IntegryApiClient.Blazor" Version="1.2.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.10" />