Completato form attività e filtri

This commit is contained in:
2025-06-16 11:58:49 +02:00
parent 0032648e76
commit 7ca4de628b
44 changed files with 1241 additions and 924 deletions

View File

@@ -19,10 +19,34 @@ public class LocalDbService
_connection.CreateTableAsync<StbActivity>(); _connection.CreateTableAsync<StbActivity>();
_connection.CreateTableAsync<VtbCliePersRif>(); _connection.CreateTableAsync<VtbCliePersRif>();
_connection.CreateTableAsync<VtbDest>(); _connection.CreateTableAsync<VtbDest>();
_connection.CreateTableAsync<StbActivityResult>();
_connection.CreateTableAsync<StbActivityType>();
_connection.CreateTableAsync<StbUser>();
}
public async Task ResetSettingsDb()
{
try
{
await _connection.ExecuteAsync("DROP TABLE IF EXISTS stb_activity_result;");
await _connection.ExecuteAsync("DROP TABLE IF EXISTS stb_activity_type;");
await _connection.ExecuteAsync("DROP TABLE IF EXISTS stb_user;");
await _connection.CreateTableAsync<StbActivityResult>();
await _connection.CreateTableAsync<StbActivityType>();
await _connection.CreateTableAsync<StbUser>();
}
catch (Exception ex)
{
Console.WriteLine($"Errore durante il reset del database(settings): {ex.Message}");
throw;
}
} }
public async Task ResetDb() public async Task ResetDb()
{ {
await ResetSettingsDb();
try try
{ {
await _connection.ExecuteAsync("DROP TABLE IF EXISTS anag_clie;"); await _connection.ExecuteAsync("DROP TABLE IF EXISTS anag_clie;");

View File

@@ -9,25 +9,7 @@ namespace Template.Maui.Core.Services;
public class ManageDataService(LocalDbService localDb, IMapper mapper) : IManageDataService public class ManageDataService(LocalDbService localDb, IMapper mapper) : IManageDataService
{ {
public Task<List<AnagClie>> GetAnagClie(Expression<Func<AnagClie, bool>>? whereCond = null) => public Task<List<T>> GetTable<T>(Expression<Func<T, bool>>? whereCond = null) where T : new() =>
localDb.Get(whereCond);
public Task<List<JtbComt>> GetJtbComt(Expression<Func<JtbComt, bool>>? whereCond = null) =>
localDb.Get(whereCond);
public Task<List<PtbPros>> GetPtbPros(Expression<Func<PtbPros, bool>>? whereCond = null) =>
localDb.Get(whereCond);
public Task<List<PtbProsRif>> GetPtbProsRif(Expression<Func<PtbProsRif, bool>>? whereCond = null) =>
localDb.Get(whereCond);
public Task<List<StbActivity>> GetStbActivity(Expression<Func<StbActivity, bool>>? whereCond = null) =>
localDb.Get(whereCond);
public Task<List<VtbCliePersRif>> GetVtbCliePersRif(Expression<Func<VtbCliePersRif, bool>>? whereCond = null) =>
localDb.Get(whereCond);
public Task<List<VtbDest>> GetVtbDest(Expression<Func<VtbDest, bool>>? whereCond = null) =>
localDb.Get(whereCond); localDb.Get(whereCond);
public async Task<List<ActivityDTO>> GetActivity(Expression<Func<StbActivity, bool>>? whereCond = null) public async Task<List<ActivityDTO>> GetActivity(Expression<Func<StbActivity, bool>>? whereCond = null)
@@ -70,7 +52,8 @@ public class ManageDataService(LocalDbService localDb, IMapper mapper) : IManage
{ {
string? ragSoc; string? ragSoc;
if (distinctClient.TryGetValue(activity.CodAnag, out ragSoc) || distinctProspect.TryGetValue(activity.CodAnag, out ragSoc)) if (distinctClient.TryGetValue(activity.CodAnag, out ragSoc) ||
distinctProspect.TryGetValue(activity.CodAnag, out ragSoc))
{ {
dto.Cliente = ragSoc; dto.Cliente = ragSoc;
} }
@@ -86,6 +69,9 @@ public class ManageDataService(LocalDbService localDb, IMapper mapper) : IManage
return returnDto; return returnDto;
} }
public Task InsertOrUpdate<T>(T objectToSave) =>
localDb.InsertOrUpdate<T>([objectToSave]);
public Task ClearDb() => public Task ClearDb() =>
localDb.ResetDb(); localDb.ResetDb();
} }

View File

@@ -1,4 +1,5 @@
using Template.Shared.Core.Interface; using Template.Shared.Core.Helpers;
using Template.Shared.Core.Interface;
namespace Template.Maui.Core.Services; namespace Template.Maui.Core.Services;
@@ -6,65 +7,80 @@ public class SyncDbService(IIntegryApiService integryApiService, LocalDbService
{ {
public async Task GetAndSaveActivity(string? dateFilter) public async Task GetAndSaveActivity(string? dateFilter)
{ {
var allActivity = await integryApiService.GetActivity(dateFilter); var allActivity = await integryApiService.RetrieveActivity(dateFilter);
if (allActivity is not null) if (!allActivity.IsNullOrEmpty())
if (dateFilter is null) if (dateFilter is null)
await localDb.InsertAll(allActivity); await localDb.InsertAll(allActivity!);
else else
await localDb.InsertOrUpdate(allActivity); await localDb.InsertOrUpdate(allActivity!);
} }
public async Task GetAndSaveCommesse(string? dateFilter) public async Task GetAndSaveCommesse(string? dateFilter)
{ {
var allCommesse = await integryApiService.GetAllCommesse(dateFilter); var allCommesse = await integryApiService.RetrieveAllCommesse(dateFilter);
if (allCommesse is not null) if (!allCommesse.IsNullOrEmpty())
if (dateFilter is null) if (dateFilter is null)
await localDb.InsertAll(allCommesse); await localDb.InsertAll(allCommesse!);
else else
await localDb.InsertOrUpdate(allCommesse); await localDb.InsertOrUpdate(allCommesse!);
} }
public async Task GetAndSaveProspect(string? dateFilter) public async Task GetAndSaveProspect(string? dateFilter)
{ {
var tasks = new List<Task>(); var taskSyncResponseDto = await integryApiService.RetrieveProspect(dateFilter);
var taskSyncResponseDto = await integryApiService.GetProspect(dateFilter);
if (taskSyncResponseDto.PtbPros is not null) if (!taskSyncResponseDto.PtbPros.IsNullOrEmpty())
tasks.Add(dateFilter is null if (dateFilter is null)
? localDb.InsertAll(taskSyncResponseDto.PtbPros) await localDb.InsertAll(taskSyncResponseDto.PtbPros!);
: localDb.InsertOrUpdate(taskSyncResponseDto.PtbPros)); else
await localDb.InsertOrUpdate(taskSyncResponseDto.PtbPros!);
if (taskSyncResponseDto.PtbProsRif is not null) if (!taskSyncResponseDto.PtbProsRif.IsNullOrEmpty())
tasks.Add(dateFilter is null if (dateFilter is null)
? localDb.Insert(taskSyncResponseDto.PtbProsRif) await localDb.InsertAll(taskSyncResponseDto.PtbProsRif!);
: localDb.InsertOrUpdate(taskSyncResponseDto.PtbProsRif)); else
await localDb.InsertOrUpdate(taskSyncResponseDto.PtbProsRif!);
await Task.WhenAll(tasks.AsEnumerable());
} }
public async Task GetAndSaveClienti(string? dateFilter) public async Task GetAndSaveClienti(string? dateFilter)
{ {
var tasks = new List<Task>(); var taskSyncResponseDto = await integryApiService.RetrieveAnagClie(dateFilter);
var taskSyncResponseDto = await integryApiService.GetAnagClie(dateFilter);
if (taskSyncResponseDto.AnagClie is not null) if (!taskSyncResponseDto.AnagClie.IsNullOrEmpty())
tasks.Add(dateFilter is null if (dateFilter is null)
? localDb.InsertAll(taskSyncResponseDto.AnagClie) await localDb.InsertAll(taskSyncResponseDto.AnagClie!);
: localDb.InsertOrUpdate(taskSyncResponseDto.AnagClie)); else
await localDb.InsertOrUpdate(taskSyncResponseDto.AnagClie!);
if (taskSyncResponseDto.VtbDest is not null) if (!taskSyncResponseDto.VtbDest.IsNullOrEmpty())
tasks.Add(dateFilter is null if (dateFilter is null)
? localDb.Insert(taskSyncResponseDto.VtbDest) await localDb.InsertAll(taskSyncResponseDto.VtbDest!);
: localDb.InsertOrUpdate(taskSyncResponseDto.VtbDest)); else
await localDb.InsertOrUpdate(taskSyncResponseDto.VtbDest!);
if (taskSyncResponseDto.VtbCliePersRif is not null) if (!taskSyncResponseDto.VtbCliePersRif.IsNullOrEmpty())
tasks.Add(dateFilter is null if (dateFilter is null)
? localDb.Insert(taskSyncResponseDto.VtbCliePersRif) await localDb.InsertAll(taskSyncResponseDto.VtbCliePersRif!);
: localDb.InsertOrUpdate(taskSyncResponseDto.VtbCliePersRif)); else
await localDb.InsertOrUpdate(taskSyncResponseDto.VtbCliePersRif!);
await Task.WhenAll(tasks.AsEnumerable());
} }
public async Task GetAndSaveSettings(string? dateFilter)
{
if (dateFilter is not null)
await localDb.ResetSettingsDb();
var settingsResponse = await integryApiService.RetrieveSettings();
if (!settingsResponse.ActivityResults.IsNullOrEmpty())
await localDb.InsertAll(settingsResponse.ActivityResults!);
if (!settingsResponse.ActivityTypes.IsNullOrEmpty())
await localDb.InsertAll(settingsResponse.ActivityTypes!);
if (!settingsResponse.StbUsers.IsNullOrEmpty())
await localDb.InsertAll(settingsResponse.StbUsers!);
}
} }

View File

@@ -1,51 +1,57 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <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" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"/>
<title>Template.Maui</title> <title>Template.Maui</title>
<base href="/" /> <base href="/"/>
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <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="https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap" rel="stylesheet">
<link href="_content/Template.Shared/css/bootstrap/bootstrap.min.css" rel="stylesheet"> <link href="_content/Template.Shared/css/bootstrap/bootstrap.min.css" rel="stylesheet">
<link href="_content/Template.Shared/css/bootstrap/bootstrap-icons.min.css" rel="stylesheet" /> <link href="_content/Template.Shared/css/bootstrap/bootstrap-icons.min.css" rel="stylesheet"/>
<link href="_content/MudBlazor/MudBlazor.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 href="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="_content/Template.Shared/css/remixicon/remixicon.css" /> <link rel="stylesheet" href="_content/Template.Shared/css/remixicon/remixicon.css"/>
<link rel="stylesheet" href="_content/Template.Shared/css/app.css" /> <link rel="stylesheet" href="_content/Template.Shared/css/app.css"/>
<link rel="stylesheet" href="_content/Template.Shared/css/default-theme.css" /> <link rel="stylesheet" href="_content/Template.Shared/css/form.css"/>
<link rel="stylesheet" href="Template.Maui.styles.css" /> <link rel="stylesheet" href="_content/Template.Shared/css/default-theme.css"/>
<link rel="icon" type="image/png" href="favicon.png" /> <link rel="stylesheet" href="Template.Maui.styles.css"/>
<link rel="icon" type="image/png" href="favicon.png"/>
</head> </head>
<body> <body>
<div class="status-bar-safe-area"></div> <div class="status-bar-safe-area"></div>
<div id="app">Loading...</div> <div id="app">
<div class="spinner-container">
<div id="blazor-error-ui"> <span class="loader"></span>
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div> </div>
</div>
<script src="_framework/blazor.webview.js" autostart="false"></script> <div id="blazor-error-ui">
<script src="_content/Template.Shared/js/bootstrap/bootstrap.bundle.min.js"></script> An unhandled error has occurred.
<!-- Add chart.js reference if chart components are used in your application. --> <a href="" class="reload">Reload</a>
<!--<script src="_content/Template.Shared/js/bootstrap/chart.umd.js" integrity="sha512-gQhCDsnnnUfaRzD8k1L5llCCV6O9HN09zClIzzeJ8OJ9MpGmIlCxm+pdCkqTwqJ4JcjbojFr79rl2F1mzcoLMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>--> <a class="dismiss">🗙</a>
<!-- Add chartjs-plugin-datalabels.min.js reference if chart components with data label feature is used in your application. --> </div>
<!--<script src="_content/Template.Shared/js/bootstrap/chartjs-plugin-datalabels.min.js" integrity="sha512-JPcRR8yFa8mmCsfrw4TNte1ZvF1e3+1SdGMslZvmrzDYxS69J7J49vkFL8u6u8PlPJK+H3voElBtUCzaXj+6ig==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>-->
<!-- Add sortable.js reference if SortableList component is used in your application. --> <script src="_framework/blazor.webview.js" autostart="false"></script>
<!--<script src="_content/Template.Shared/js/bootstrap/Sortable.min.js"></script>--> <script src="_content/Template.Shared/js/bootstrap/bootstrap.bundle.min.js"></script>
<script src="_content/MudBlazor/MudBlazor.min.js"></script> <!-- Add chart.js reference if chart components are used in your application. -->
<script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script> <!--<script src="_content/Template.Shared/js/bootstrap/chart.umd.js" integrity="sha512-gQhCDsnnnUfaRzD8k1L5llCCV6O9HN09zClIzzeJ8OJ9MpGmIlCxm+pdCkqTwqJ4JcjbojFr79rl2F1mzcoLMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>-->
<script src="_content/Template.Shared/js/main.js"></script> <!-- Add chartjs-plugin-datalabels.min.js reference if chart components with data label feature is used in your application. -->
<script src="_content/Template.Shared/js/calendar.js"></script> <!--<script src="_content/Template.Shared/js/bootstrap/chartjs-plugin-datalabels.min.js" integrity="sha512-JPcRR8yFa8mmCsfrw4TNte1ZvF1e3+1SdGMslZvmrzDYxS69J7J49vkFL8u6u8PlPJK+H3voElBtUCzaXj+6ig==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>-->
<!-- Add sortable.js reference if SortableList component is used in your application. -->
<!--<script src="_content/Template.Shared/js/bootstrap/Sortable.min.js"></script>-->
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
<script src="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js"></script>
<script src="_content/Template.Shared/js/main.js"></script>
<script src="_content/Template.Shared/js/calendar.js"></script>
<script src="_content/Template.Shared/js/bottomSheet.js"></script>
</body> </body>

View File

@@ -0,0 +1,151 @@
@using Template.Shared.Core.Dto
@using Template.Shared.Core.Entity
@using Template.Shared.Core.Helpers.Enum
@using Template.Shared.Core.Interface
@inject IManageDataService manageData
<div class="bottom-sheet-backdrop @(IsSheetVisible ? "show" : "")" @onclick="CloseBottomSheet"></div>
<div class="bottom-sheet-container @(IsSheetVisible ? "show" : "")">
<div class="bottom-sheet">
<div class="title">
<MudText Typo="Typo.h6">
<b>Filtri</b>
</MudText>
<MudIconButton Icon="@Icons.Material.Filled.Close" OnClick="CloseBottomSheet"/>
</div>
<div class="input-card clearButton">
<MudTextField T="string?" Placeholder="Cerca..." Variant="Variant.Text" @bind-Value="Filter.Text" DebounceInterval="500"/>
<MudIconButton Class="closeIcon" Icon="@Icons.Material.Filled.Close" OnClick="() => Filter.Text = null"/>
</div>
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">Assegnata a</span>
<MudSelectExtended SearchBox="true"
ItemCollection="Users.Select(x => x.UserName).ToList()"
SelectAllPosition="SelectAllPosition.NextToSearchBox"
SelectAll="true"
NoWrap="true"
MultiSelection="true"
MultiSelectionTextFunc="@(new Func<List<string>, string>(GetMultiSelectionUser))"
FullWidth="true" T="string"
Variant="Variant.Text"
Virtualize="true"
@bind-SelectedValues="Filter.User"
Class="customIcon-select"
AdornmentIcon="@Icons.Material.Filled.Code"/>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Tipo</span>
<MudSelectExtended FullWidth="true"
T="string?"
Variant="Variant.Text"
@bind-Value="Filter.Type"
Class="customIcon-select"
AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var type in ActivityType)
{
<MudSelectItemExtended Class="custom-item-select" Value="@type.ActivityTypeId">@type.ActivityTypeId</MudSelectItemExtended>
}
</MudSelectExtended>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Esito</span>
<MudSelectExtended FullWidth="true"
T="string?"
Variant="Variant.Text"
@bind-Value="Filter.Result"
Class="customIcon-select"
AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var result in ActivityResult)
{
<MudSelectItemExtended Class="custom-item-select" Value="@result.ActivityResultId">@result.ActivityResultId</MudSelectItemExtended>
}
</MudSelectExtended>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Categoria</span>
<MudSelectExtended FullWidth="true"
T="ActivityCategoryEnum?"
Variant="Variant.Text"
@bind-Value="Filter.Category"
Class="customIcon-select"
AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var category in CategoryList)
{
<MudSelectItemExtended T="ActivityCategoryEnum?" Class="custom-item-select" Value="@category">@category.ConvertToHumanReadable()</MudSelectItemExtended>
}
</MudSelectExtended>
</div>
</div>
<div class="button-section">
<MudButton OnClick="() => Filter = new FilterActivityDTO()" Variant="Variant.Outlined" Color="Color.Error">Pulisci</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="OnFilterButton">Filtra</MudButton>
</div>
</div>
</div>
@code {
[Parameter] public bool IsSheetVisible { get; set; }
[Parameter] public EventCallback<bool> IsSheetVisibleChanged { get; set; }
[Parameter] public FilterActivityDTO Filter { get; set; }
[Parameter] public EventCallback<FilterActivityDTO> FilterChanged { get; set; }
private List<StbActivityResult> ActivityResult { get; set; } = [];
private List<StbActivityType> ActivityType { get; set; } = [];
private List<StbUser> Users { get; set; } = [];
private List<ActivityCategoryEnum> CategoryList { get; set; } = [];
protected override async Task OnParametersSetAsync()
{
if (IsSheetVisible)
await LoadData();
}
private string GetMultiSelectionUser(List<string> selectedValues)
{
return $"{selectedValues.Count} Utent{(selectedValues.Count != 1 ? "i selezionati" : "e selezionato")}";
}
private async Task LoadData()
{
Users = await manageData.GetTable<StbUser>();
ActivityResult = await manageData.GetTable<StbActivityResult>();
ActivityType = await manageData.GetTable<StbActivityType>(x => x.FlagTipologia.Equals("A"));
CategoryList = ActivityCategoryHelper.AllActivityCategory;
StateHasChanged();
}
private void CloseBottomSheet()
{
IsSheetVisible = false;
IsSheetVisibleChanged.InvokeAsync(IsSheetVisible);
}
private void OnFilterButton()
{
FilterChanged.InvokeAsync(Filter);
CloseBottomSheet();
}
}

View File

@@ -0,0 +1,56 @@
.bottom-sheet-backdrop {
position: fixed;
inset: 0;
background-color: rgba(165, 165, 165, 0.5);
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
z-index: 1002;
}
.bottom-sheet-backdrop.show {
opacity: 1;
pointer-events: auto;
}
.bottom-sheet-container {
position: fixed;
bottom: -100%;
left: 0;
right: 0;
transition: bottom 0.3s ease;
z-index: 1003;
}
.bottom-sheet-container.show {
bottom: 0;
}
.bottom-sheet {
background-color: var(--mud-palette-surface);
border-top-left-radius: 16px;
border-top-right-radius: 16px;
padding: 4px 16px 16px;
box-shadow: 0 -2px 10px rgba(165, 165, 165, 0.5);
}
.clearButton ::deep .mud-icon-button {
padding: 4px !important;
}
.bottom-sheet ::deep .closeIcon .mud-icon-root {
border-radius: 50%;
padding: 2px;
min-width: 15px;
min-height: 15px;
padding: 4px;
background: var(--mud-palette-gray-light);
color: var(--mud-palette-surface);
}
.button-section {
display: flex;
justify-content: end;
gap: .75rem;
margin-top: 2rem;
}

View File

@@ -22,11 +22,7 @@
{ {
@if (ShowFilter) @if (ShowFilter)
{ {
<MudIconButton Icon="@Icons.Material.Outlined.FilterAlt" Color="Color.Dark"/> <MudIconButton OnClick="OnFilterToggle" Icon="@Icons.Material.Outlined.FilterAlt" Color="Color.Dark" />
}
@if (ShowNotifications)
{
@* <MudIconButton Icon="@Icons.Material.Filled.Notifications" Color="Color.Dark"/> *@
} }
@if (ShowCalendarToggle) @if (ShowCalendarToggle)
{ {
@@ -53,6 +49,8 @@
[Parameter] public bool Back { get; set; } [Parameter] public bool Back { get; set; }
[Parameter] public string BackTo { get; set; } = ""; [Parameter] public string BackTo { get; set; } = "";
[Parameter] public EventCallback OnFilterToggle { get; set; }
[Parameter] public bool Cancel { get; set; } [Parameter] public bool Cancel { get; set; }
[Parameter] public EventCallback OnCancel { get; set; } [Parameter] public EventCallback OnCancel { get; set; }
[Parameter] public string? LabelSave { get; set; } [Parameter] public string? LabelSave { get; set; }
@@ -76,7 +74,7 @@
} }
await JS.InvokeVoidAsync("goBack"); await JS.InvokeVoidAsync("goBack");
} }
} }

View File

@@ -0,0 +1,23 @@
@using Template.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,156 @@
.success-checkmark {
width: 80px;
height: 80px;
margin: 0 auto;
}
.success-checkmark .check-icon {
width: 80px;
height: 80px;
position: relative;
border-radius: 50%;
box-sizing: content-box;
border: 4px solid var(--mud-palette-success);
}
.success-checkmark .check-icon::before {
top: 3px;
left: -2px;
width: 30px;
transform-origin: 100% 50%;
border-radius: 100px 0 0 100px;
}
.success-checkmark .check-icon::after {
top: 0;
left: 30px;
width: 60px;
transform-origin: 0 50%;
border-radius: 0 100px 100px 0;
animation: rotate-circle 4.25s ease-in;
}
.success-checkmark .check-icon::before,
.success-checkmark .check-icon::after {
content: '';
height: 100px;
position: absolute;
transform: rotate(-45deg);
z-index: 2;
}
.icon-line {
height: 5px;
background-color: var(--mud-palette-success);
display: block;
border-radius: 2px;
position: absolute;
z-index: 10;
}
.icon-line.line-tip {
top: 46px;
left: 14px;
width: 25px;
transform: rotate(45deg);
animation: icon-line-tip 0.75s;
}
.icon-line.line-long {
top: 38px;
right: 8px;
width: 47px;
transform: rotate(-45deg);
animation: icon-line-long 0.75s;
}
.icon-circle {
top: -4px;
left: -4px;
z-index: 10;
width: 80px;
height: 80px;
border-radius: 50%;
position: absolute;
box-sizing: content-box;
border: 4px solid var(--mud-palette-success);
}
.icon-fix {
top: 8px;
width: 5px;
left: 26px;
z-index: 1;
height: 85px;
position: absolute;
transform: rotate(-45deg);
}
@keyframes rotate-circle {
0% { transform: rotate(-45deg); }
5% { transform: rotate(-45deg); }
12% { transform: rotate(-405deg); }
100% { transform: rotate(-405deg); }
}
@keyframes icon-line-tip {
0% {
width: 0;
left: 1px;
top: 19px;
}
54% {
width: 0;
left: 1px;
top: 19px;
}
70% {
width: 50px;
left: -8px;
top: 37px;
}
84% {
width: 17px;
left: 21px;
top: 48px;
}
100% {
width: 25px;
left: 14px;
top: 45px;
}
}
@keyframes icon-line-long {
0% {
width: 0;
right: 46px;
top: 54px;
}
65% {
width: 0;
right: 46px;
top: 54px;
}
84% {
width: 55px;
right: 0px;
top: 35px;
}
100% {
width: 47px;
right: 8px;
top: 38px;
}
}

View File

@@ -1,131 +0,0 @@
@using Template.Shared.Core.Dto
@using Template.Shared.Components.Layout
@using Template.Shared.Core.Interface
@inject IManageDataService manageData
<MudDialog Class="customDialog-form">
<DialogContent>
<HeaderLayout Cancel="true" OnCancel="() => MudDialog.Cancel()" LabelSave="@LabelSave" ShowNotifications="false" Title="@(IsNew ? "Nuova" : $"{ActivityModel.ActivityId}")" />
<div class="content">
<div class="input-card">
<MudTextField T="string?" Placeholder="Descrizione" Variant="Variant.Text" Lines="3" @bind-Value="ActivityModel.ActivityDescription" @bind-Value:after="OnAfterChangeValue" />
</div>
<div class="input-card">
<div class="form-container">
<MudInput T="string?" Placeholder="Cliente" @bind-Value="ActivityModel.Cliente" @bind-Value:after="OnAfterChangeValue" />
</div>
<div class="divider"></div>
<div class="form-container">
<MudInput T="string?" Placeholder="Commessa" @bind-Value="ActivityModel.Commessa" @bind-Value:after="OnAfterChangeValue" />
</div>
</div>
<div class="input-card">
<div class="form-container">
<span>Inizio</span>
<MudTextField T="DateTime?" Format="yyyy-MM-ddTHH:mm" InputType="InputType.DateTimeLocal" @bind-Value="ActivityModel.EstimatedTime" @bind-Value:after="OnAfterChangeValue" />
</div>
<div class="divider"></div>
<div class="form-container">
<span>Fine</span>
<MudTextField T="DateTime?" Format="yyyy-MM-ddTHH:mm" InputType="InputType.DateTimeLocal" @bind-Value="ActivityModel.EstimatedEndtime" @bind-Value:after="OnAfterChangeValue" />
</div>
<div class="divider"></div>
<div class="form-container">
<span>Avviso</span>
<MudSwitch T="bool" Disabled="true" Color="Color.Primary" />
</div>
</div>
<div class="input-card">
<div class="form-container text-align-end">
<span>Assegnata a</span>
<MudInput T="string" Placeholder="Nessuno" @bind-Value="ActivityModel.UserName" @bind-Value:after="OnAfterChangeValue" />
</div>
<div class="divider"></div>
<div class="form-container">
<span>Tipo</span>
<MudSelect T="string?" Variant="Variant.Text" @bind-Value="ActivityModel.ActivityTypeId" @bind-Value:after="OnAfterChangeValue" Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var state in ActivityResult)
{
<MudSelectItem Value="@state">@state</MudSelectItem>
}
</MudSelect>
</div>
<div class="divider"></div>
<div class="form-container">
<span>Esito</span>
<MudSelect T="string?" Variant="Variant.Text" @bind-Value="ActivityModel.ActivityResultId" @bind-Value:after="OnAfterChangeValue" Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var state in ActivityResult)
{
<MudSelectItem Value="@state">@state</MudSelectItem>
}
</MudSelect>
</div>
</div>
<div class="input-card">
<MudTextField T="string?" Placeholder="Note" Variant="Variant.Text" Lines="4" @bind-Value="ActivityModel.Note" @bind-Value:after="OnAfterChangeValue" />
</div>
</div>
</DialogContent>
</MudDialog>
@code {
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; }
[Parameter] public string? Id { get; set; }
private ActivityDTO OriginalModel { get; set; } = new();
private ActivityDTO ActivityModel { get; set; } = new();
private List<ActivityResultDTO> ActivityResult { get; set; } = [];
private bool IsNew => Id.IsNullOrEmpty();
private bool _selectEstimatedTime;
private bool _selectEstimatedEndTime;
private string? LabelSave { get; set; }
protected override async Task OnInitializedAsync()
{
LabelSave = IsNew ? "Aggiungi" : null;
if (!Id.IsNullOrEmpty())
ActivityModel = (await manageData.GetActivity(x => x.ActivityId.Equals(Id))).Last();
if (IsNew)
{
ActivityModel.EstimatedTime = DateTime.Today.Add(TimeSpan.FromHours(DateTime.Now.Hour));
ActivityModel.EstimatedEndtime = DateTime.Today.Add(TimeSpan.FromHours(DateTime.Now.Hour) + TimeSpan.FromHours(1));
}
OriginalModel = ActivityModel.Clone();
}
private void OnAfterChangeValue()
{
if (OriginalModel.Equals(ActivityModel))
LabelSave = "Aggiorna";
StateHasChanged();
}
}

View File

@@ -1,61 +0,0 @@
.customDialog-form .content ::deep {
height: calc(100vh - (.6rem + 40px));
overflow: auto;
-ms-overflow-style: none;
scrollbar-width: none;
}
.customDialog-form .content::-webkit-scrollbar {
display: none;
}
.input-card {
width: 100%;
background: var(--mud-palette-background-gray);
border-radius: 9px;
padding: .5rem 1rem;
margin-bottom: 1.5rem;
}
.input-card ::deep > .divider { margin: 0 !important; }
.form-container {
display: flex;
justify-content: space-between;
align-items: center;
min-height: 35px;
}
.form-container > span {
font-weight: 600;
width: 50%;
}
.dateTime-picker {
display: flex;
gap: .3rem;
flex-direction: row;
align-items: center;
}
/*Custom mudBlazor*/
.form-container ::deep .mud-input.mud-input-underline:before { border-bottom: none !important; }
.form-container ::deep .mud-input.mud-input-underline:after { border-bottom: none !important; }
.form-container.text-align-end ::deep .mud-input-slot { text-align: end; }
.input-card ::deep .mud-input.mud-input-underline:before { border-bottom: none !important; }
.input-card ::deep .mud-input.mud-input-underline:after { border-bottom: none !important; }
.form-container ::deep .customIcon-select .mud-icon-root.mud-svg-icon {
rotate: 90deg !important;
font-size: 1.1rem;
}
.input-card ::deep .mud-input {
width: 100%;
font-weight: 500;
}

View File

@@ -4,13 +4,14 @@
@using Template.Shared.Components.Layout @using Template.Shared.Components.Layout
@using Template.Shared.Components.SingleElements @using Template.Shared.Components.SingleElements
@using Template.Shared.Components.Layout.Spinner @using Template.Shared.Components.Layout.Spinner
@inject IManageDataService manageData @using Template.Shared.Components.Layout.BottomSheet
@inject IDialogService Dialog @inject IManageDataService ManageData
@inject IJSRuntime JS @inject IJSRuntime JS
<HeaderLayout Title="@CurrentMonth.ToString("MMMM yyyy", new System.Globalization.CultureInfo("it-IT")).FirstCharToUpper()" <HeaderLayout Title="@CurrentMonth.ToString("MMMM yyyy", new System.Globalization.CultureInfo("it-IT")).FirstCharToUpper()"
ShowFilter="true" ShowFilter="true"
ShowCalendarToggle="true" ShowCalendarToggle="true"
OnFilterToggle="ToggleFilter"
OnCalendarToggle="ToggleExpanded"/> OnCalendarToggle="ToggleExpanded"/>
<div @ref="weekSliderRef" class="container week-slider @(Expanded ? "expanded" : "") @(SliderAnimation)"> <div @ref="weekSliderRef" class="container week-slider @(Expanded ? "expanded" : "") @(SliderAnimation)">
@@ -34,7 +35,7 @@
var day = new DateTime(CurrentMonth.Year, CurrentMonth.Month, d); var day = new DateTime(CurrentMonth.Year, CurrentMonth.Month, d);
var isSelected = IsSameDay(day, SelectedDate); var isSelected = IsSameDay(day, SelectedDate);
var isToday = IsSameDay(day, DateTime.Today); var isToday = IsSameDay(day, DateTime.Today);
var events = GetEventsForDay(day); var events = ReturnFilteredActivity(day);
<div class="day @(isSelected ? "selected" : (isToday ? "today" : ""))" <div class="day @(isSelected ? "selected" : (isToday ? "today" : ""))"
@onclick="() => SelezionaDataDalMese(day)"> @onclick="() => SelezionaDataDalMese(day)">
@@ -69,10 +70,10 @@
<div class="day @(isSelected ? "selected" : (isToday ? "today" : ""))" <div class="day @(isSelected ? "selected" : (isToday ? "today" : ""))"
@onclick="() => SelezionaData(day)"> @onclick="() => SelezionaData(day)">
<div>@day.Day</div> <div>@day.Day</div>
@if (GetEventsForDay(day).Any()) @if (ReturnFilteredActivity(day).Any())
{ {
<div class="event-dot-container" style="margin-top: 2px;"> <div class="event-dot-container" style="margin-top: 2px;">
@foreach (var cat in GetEventsForDay(day).Select(x => x.Category).Distinct()) @foreach (var cat in ReturnFilteredActivity(day).Select(x => x.Category).Distinct())
{ {
<div class="event-dot @cat.ConvertToHumanReadable()" title="@cat.ConvertToHumanReadable()"></div> <div class="event-dot @cat.ConvertToHumanReadable()" title="@cat.ConvertToHumanReadable()"></div>
} }
@@ -92,7 +93,7 @@
else if (FilteredActivities is { Count: > 0 }) else if (FilteredActivities is { Count: > 0 })
{ {
<Virtualize Items="FilteredActivities" Context="activity"> <Virtualize Items="FilteredActivities" Context="activity">
<ActivityCard Activity="activity" /> <ActivityCard Activity="activity" ActivityChanged="OnActivityChanged"/>
</Virtualize> </Virtualize>
} }
else else
@@ -101,6 +102,8 @@
} }
</div> </div>
<FilterActivity @bind-IsSheetVisible="OpenFilter" @bind-Filter="Filter" @bind-Filter:after="ApplyFilter"/>
@code { @code {
// Stato UI // Stato UI
@@ -124,6 +127,10 @@
private int DaysInMonth => DateTime.DaysInMonth(CurrentMonth.Year, CurrentMonth.Month); private int DaysInMonth => DateTime.DaysInMonth(CurrentMonth.Year, CurrentMonth.Month);
private int StartOffset => (int)CurrentMonth.DayOfWeek == 0 ? 6 : (int)CurrentMonth.DayOfWeek - 1; private int StartOffset => (int)CurrentMonth.DayOfWeek == 0 ? 6 : (int)CurrentMonth.DayOfWeek - 1;
//Filtri
private bool OpenFilter { get; set; }
private FilterActivityDTO Filter { get; set; } = new();
private int EndOffset private int EndOffset
{ {
get get
@@ -147,10 +154,17 @@
{ {
if (firstRender) if (firstRender)
{ {
Filter.User = new HashSet<string> { UserSession.User.Username };
dotNetHelper = DotNetObjectReference.Create(this); dotNetHelper = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("calendarSwipe.register", weekSliderRef, dotNetHelper); await JS.InvokeVoidAsync("calendarSwipe.register", weekSliderRef, dotNetHelper);
_internalMonth = new DateTime(SelectedDate.Year, SelectedDate.Month, 1); _internalMonth = new DateTime(SelectedDate.Year, SelectedDate.Month, 1);
await LoadMonthData(); await LoadMonthData();
if (!Expanded)
ApplyFilter();
StateHasChanged();
} }
} }
@@ -249,7 +263,7 @@
// Carica tutte le attività del mese corrente visualizzato // Carica tutte le attività del mese corrente visualizzato
var start = CurrentMonth; var start = CurrentMonth;
var end = start.AddDays(DaysInMonth - 1); var end = start.AddDays(DaysInMonth - 1);
var activities = await manageData.GetActivity(x => var activities = await ManageData.GetActivity(x =>
(x.EffectiveDate == null && x.EstimatedDate >= start && x.EstimatedDate <= end) || (x.EffectiveDate == null && x.EstimatedDate >= start && x.EstimatedDate <= end) ||
(x.EffectiveDate >= start && x.EffectiveDate <= end)); (x.EffectiveDate >= start && x.EffectiveDate <= end));
MonthActivities = activities.OrderBy(x => x.EffectiveDate ?? x.EstimatedDate).ToList(); MonthActivities = activities.OrderBy(x => x.EffectiveDate ?? x.EstimatedDate).ToList();
@@ -272,7 +286,7 @@
await LoadMonthData(); await LoadMonthData();
} }
FilteredActivities = GetEventsForDay(day); ApplyFilter();
StateHasChanged(); StateHasChanged();
} }
@@ -280,7 +294,7 @@
private async Task SelezionaDataDalMese(DateTime day) private async Task SelezionaDataDalMese(DateTime day)
{ {
SelectedDate = day; SelectedDate = day;
FilteredActivities = GetEventsForDay(day); ApplyFilter();
// Chiudi la vista mese e passa alla settimana, con animazione // Chiudi la vista mese e passa alla settimana, con animazione
SliderAnimation = "collapse-animation"; SliderAnimation = "collapse-animation";
StateHasChanged(); StateHasChanged();
@@ -306,4 +320,63 @@
{ {
dotNetHelper?.Dispose(); dotNetHelper?.Dispose();
} }
private async Task OnActivityChanged(string activityId)
{
var newActivity = await ManageData.GetActivity(x => x.ActivityId.Equals(activityId));
var indexActivity = MonthActivities?.FindIndex(x => x.ActivityId.Equals(activityId));
if (indexActivity != null && !newActivity.IsNullOrEmpty())
{
MonthActivities![indexActivity.Value] = newActivity[0];
}
ApplyFilter();
StateHasChanged();
}
private void ToggleFilter()
{
OpenFilter = !OpenFilter;
StateHasChanged();
}
private void ApplyFilter()
{
FilteredActivities = GetEventsForDay(SelectedDate);
if (!Filter.ClearFilter)
{
FilteredActivities = GetEventsForDay(SelectedDate)?
.Where(x =>
(!Filter.Text.IsNullOrEmpty() && x.ActivityDescription != null && x.ActivityDescription.ContainsIgnoreCase(Filter.Text!)) ||
(x.ActivityTypeId != null && !Filter.Type.IsNullOrEmpty() && x.ActivityTypeId.Equals(Filter.Type)) ||
(x.ActivityResultId != null && !Filter.Result.IsNullOrEmpty() && x.ActivityResultId.Equals(Filter.Result)) ||
(x.UserName != null && !Filter.User.IsNullOrEmpty() && Filter.User!.Contains(x.UserName)) ||
(Filter.Category != null && x.Category.Equals(Filter.Category))
)
.ToList() ?? [];
}
StateHasChanged();
}
private List<ActivityDTO> ReturnFilteredActivity(DateTime day)
{
if (!Filter.ClearFilter)
{
return GetEventsForDay(day)?
.Where(x =>
(!Filter.Text.IsNullOrEmpty() && x.ActivityDescription != null && x.ActivityDescription.ContainsIgnoreCase(Filter.Text!)) ||
(x.ActivityTypeId != null && !Filter.Type.IsNullOrEmpty() && x.ActivityTypeId.Equals(Filter.Type)) ||
(x.ActivityResultId != null && !Filter.Result.IsNullOrEmpty() && x.ActivityResultId.Equals(Filter.Result)) ||
(x.UserName != null && !Filter.User.IsNullOrEmpty() && Filter.User!.Contains(x.UserName)) ||
(Filter.Category != null && x.Category.Equals(Filter.Category))
)
.ToList() ?? [];
}
return GetEventsForDay(day);
}
} }

View File

@@ -98,17 +98,23 @@
.container-button ::deep .button-settings { border: none !important; } .container-button ::deep .button-settings { border: none !important; }
.container-button ::deep .button-settings .mud-icon-root { .container-button ::deep .button-settings .mud-icon-root {
border: 1px solid var(--mud-palette-gray-light);
border-radius: 6px; border-radius: 6px;
padding: 2px; padding: 2px;
min-width: 25px; min-width: 25px;
min-height: 25px; min-height: 25px;
box-shadow: inset 0 3px 5px rgba(200, 200, 200, 0.5);
} }
.container-button ::deep .button-settings.green-icon .mud-icon-root { color: var(--mud-palette-success-darken); } .container-button ::deep .button-settings.green-icon .mud-icon-root {
border: 1px solid var(--mud-palette-success);
background: hsl(from var(--mud-palette-success-lighten) h s 95%);
color: var(--mud-palette-success-darken);
}
.container-button ::deep .button-settings.red-icon .mud-icon-root { color: var(--mud-palette-error); } .container-button ::deep .button-settings.red-icon .mud-icon-root {
border: 1px solid var(--mud-palette-error);
background: hsl(from var(--mud-palette-error-lighten) h s 95%);
color: var(--mud-palette-error-darken);
}
.container-button ::deep .button-settings .mud-button-label { .container-button ::deep .button-settings .mud-button-label {
justify-content: flex-start; justify-content: flex-start;

View File

@@ -21,6 +21,7 @@
Elements["Commesse"] = false; Elements["Commesse"] = false;
Elements["Clienti"] = false; Elements["Clienti"] = false;
Elements["Prospect"] = false; Elements["Prospect"] = false;
Elements["Impostazioni"] = false;
} }
protected override async Task OnAfterRenderAsync(bool firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
@@ -34,7 +35,13 @@
await manageData.ClearDb(); await manageData.ClearDb();
} }
await Task.WhenAll(RunAndTrack(SetActivity), RunAndTrack(SetClienti), RunAndTrack(SetProspect), RunAndTrack(SetCommesse)); await Task.WhenAll(
RunAndTrack(SetActivity),
RunAndTrack(SetClienti),
RunAndTrack(SetProspect),
RunAndTrack(SetCommesse),
RunAndTrack(SetSettings)
);
} }
} }
@@ -57,10 +64,7 @@
private async Task SetActivity() private async Task SetActivity()
{ {
await Task.Run(async () => await Task.Run(async () => { await syncDb.GetAndSaveActivity(DateFilter); });
{
await syncDb.GetAndSaveActivity(DateFilter);
});
Elements["Attività"] = true; Elements["Attività"] = true;
StateHasChanged(); StateHasChanged();
@@ -68,10 +72,7 @@
private async Task SetClienti() private async Task SetClienti()
{ {
await Task.Run(async () => await Task.Run(async () => { await syncDb.GetAndSaveClienti(DateFilter); });
{
await syncDb.GetAndSaveClienti(DateFilter);
});
Elements["Clienti"] = true; Elements["Clienti"] = true;
StateHasChanged(); StateHasChanged();
@@ -79,10 +80,7 @@
private async Task SetProspect() private async Task SetProspect()
{ {
await Task.Run(async () => await Task.Run(async () => { await syncDb.GetAndSaveProspect(DateFilter); });
{
await syncDb.GetAndSaveProspect(DateFilter);
});
Elements["Prospect"] = true; Elements["Prospect"] = true;
StateHasChanged(); StateHasChanged();
@@ -90,13 +88,18 @@
private async Task SetCommesse() private async Task SetCommesse()
{ {
await Task.Run(async () => await Task.Run(async () => { await syncDb.GetAndSaveCommesse(DateFilter); });
{
await syncDb.GetAndSaveCommesse(DateFilter);
});
Elements["Commesse"] = true; Elements["Commesse"] = true;
StateHasChanged(); StateHasChanged();
} }
private async Task SetSettings()
{
await Task.Run(async () => { await syncDb.GetAndSaveSettings(DateFilter); });
Elements["Impostazioni"] = true;
StateHasChanged();
}
} }

View File

@@ -1,73 +0,0 @@
@using Template.Shared.Core.Dto
@using Template.Shared.Core.Interface
@using Template.Shared.Components.Layout.Spinner
@inject IManageDataService manageData
<div class="calendar">
@if (Load)
{
<SpinnerLayout FullScreen="false" />
}
else
{
@if (!Activities.IsNullOrEmpty())
{
@foreach (var activity in Activities!)
{
<ActivityCard Activity="activity"/>
}
}
else
{
<NoDataAvailable Text="Nessuna attività trovata" ImageSource="_content/Template.Shared/images/undraw_file-search_cbur.svg"/>
}
}
</div>
@code
{
[Parameter] public required DateTime? Date { get; set; }
[Parameter] public EventCallback<DateTime?> DateChanged { get; set; }
private List<ActivityDTO>? Activities { get; set; }
private bool Load { get; set; } = true;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await LoadData();
}
}
protected override async Task OnParametersSetAsync()
{
await LoadData();
}
private async Task LoadData()
{
Load = true;
StateHasChanged();
await Task.Delay(500);
var refreshActivity = await RefreshActivity();
Activities = refreshActivity;
Load = false;
StateHasChanged();
}
private async Task<List<ActivityDTO>> RefreshActivity()
{
var activityDto = await Task.Run(async () =>
{
return (await manageData.GetActivity(x =>
(x.EffectiveDate == null && x.EstimatedDate.Equals(Date)) || x.EffectiveDate.Equals(Date)))
.OrderBy(x => x.EffectiveDate ?? x.EstimatedDate)
.ToList();
});
return activityDto;
}
}

View File

@@ -1,17 +0,0 @@
.calendar {
width: 100%;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
gap: 1rem;
overflow-y: auto;
overflow-x: hidden;
padding-bottom: 1rem;
}
.calendar::-webkit-scrollbar { display: none; }
.calendar {
-ms-overflow-style: none;
scrollbar-width: none;
}

View File

@@ -1,150 +0,0 @@
@using Template.Shared.Core.Dto
@using Template.Shared.Core.Interface
@inject IManageDataService manageData
<div class="calendar-activity">
<div class="calendar">
@foreach (var nomeGiorno in _giorniSettimana)
{
<div class="calendar-header">@nomeGiorno</div>
}
@for (var i = 0; i < StartDays; i++)
{
<div class="calendar-day disabled @(i == 0 ? "radiusTopLeft" : "")"></div>
}
@for (var day = 1; day <= DaysInMonth; day++)
{
var currentDate = new DateTime(Date.Year, Date.Month, day);
var events = GetEventsForDay(currentDate);
var daySelected = SelectedDate == currentDate;
var isToday = currentDate == DateTime.Today;
var topRight = StartDays == 0 ? 7 : 7 - StartDays;
var bottomLeft = DaysInMonth - (6 - EndDays);
var categoryActivityCount = events.Select(x => x.Category).Distinct().ToList();
<div @onclick="() => SelectDay(currentDate)" class="calendar-day @(isToday ? "today" : daySelected ? "selectedDay" : "")
@(StartDays == 0 && day == 1 ? "radiusTopLeft" : "")
@(EndDays == 0 && day == DaysInMonth ? "radiusBottomRight" : "")
@(bottomLeft == day ? "radiusBottomLeft" : "")
@(topRight == day ? "radiusTopRight" : "")">
<div class="calendar-day-wrapper">
<span class="titleDay">@day</span>
@if (events.Any())
{
<div class="event-dot-container">
@foreach (var activityCategory in categoryActivityCount)
{
<div class="event-dot @activityCategory.ConvertToHumanReadable()"></div>
}
</div>
}
</div>
</div>
}
@for (var i = 0; i < EndDays; i++)
{
<div class="calendar-day disabled @(i + 1 == EndDays ? "radiusBottomRight" : "")"></div>
}
</div>
<div class="activityContainer">
@if (!FilteredActivityList.IsNullOrEmpty())
{
@foreach (var activity in FilteredActivityList!)
{
<ActivityCard Activity="activity"/>
}
}
</div>
</div>
@code
{
[Parameter] public required DateTime Date { get; set; }
[Parameter] public EventCallback<DateTime> DateChanged { get; set; }
private List<ActivityDTO> ActivityList { get; set; } = [];
private List<ActivityDTO> FilteredActivityList { get; set; } = [];
private DateTime SelectedDate { get; set; } = DateTime.Today;
private int DaysInMonth { get; set; }
private int StartDays { get; set; }
private int EndDays { get; set; }
readonly string[] _giorniSettimana = ["Lu", "Ma", "Me", "Gi", "Ve", "Sa", "Do"];
protected override async Task OnInitializedAsync()
{
await ChangeMonth();
}
protected override async Task OnParametersSetAsync()
{
await ChangeMonth();
}
private async Task ChangeMonth()
{
var firstDay = Date;
DaysInMonth = DateTime.DaysInMonth(firstDay.Year, firstDay.Month);
var dayOfWeek = (int)firstDay.DayOfWeek;
StartDays = dayOfWeek == 0 ? 6 : dayOfWeek - 1;
var tempTotalCell = (int)Math.Ceiling((double)(DaysInMonth + StartDays) / 7);
var totalCell = tempTotalCell * 7;
EndDays = totalCell - (DaysInMonth + StartDays);
await LoadData();
}
private async Task LoadData()
{
// Load = true;
// StateHasChanged();
await Task.Delay(500);
var refreshActivity = await RefreshActivity();
ActivityList = refreshActivity;
// Load = false;
StateHasChanged();
}
private async Task<List<ActivityDTO>> RefreshActivity()
{
var startDate = Date;
var endDate = Date.AddDays(DateTime.DaysInMonth(startDate.Year, startDate.Month) - 1);
var dateRange = new DateRange(Date, endDate);
var activityDto = await Task.Run(async () =>
{
return (await manageData.GetActivity(x =>
(x.EffectiveDate == null && x.EstimatedDate >= dateRange.Start && x.EstimatedDate <= dateRange.End) ||
(x.EffectiveDate >= dateRange.Start && x.EffectiveDate <= dateRange.End)
))
.OrderBy(x => x.EffectiveDate ?? x.EstimatedDate)
.ToList();
});
return activityDto;
}
private List<ActivityDTO> GetEventsForDay(DateTime day)
{
return ActivityList.IsNullOrEmpty() ? [] : ActivityList.Where(x => (x.EffectiveDate ?? x.EstimatedDate) == day.Date).ToList();
}
private void SelectDay(DateTime currentDate)
{
SelectedDate = currentDate;
StateHasChanged();
FilteredActivityList = GetEventsForDay(currentDate);
}
}

View File

@@ -1,101 +0,0 @@
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
}
.calendar-header, .calendar-day {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
min-height: 65px;
font-size: 0.85rem;
padding: 4px;
}
.calendar-day { border: 1px solid var(--mud-palette-gray-light); }
.calendar-day.disabled { border: 1px solid hsl(from var(--mud-palette-gray-light) h s 88%); }
.calendar-header {
font-weight: bold;
min-height: 25px;
display: flex;
justify-content: end;
}
.today > .calendar-day-wrapper > .titleDay {
background-color: var(--mud-palette-primary);
color: var(--mud-palette-appbar-text);
font-weight: 700;
}
.selectedDay > .calendar-day-wrapper > .titleDay {
border: 1px solid var(--mud-palette-primary);
font-weight: 700;
}
.calendar-day-wrapper > .titleDay {
padding: 6px;
border-radius: 50%;
position: absolute;
line-height: normal;
}
.event-dot-container {
position: absolute;
bottom: 0;
width: 100%;
display: flex;
flex-direction: column;
gap: .2rem;
}
.event-dot {
width: 100%;
height: 6px;
border-radius: 4px;
background-color: var(--mud-palette-secondary);
}
.event-dot.memo { background-color: var(--mud-palette-info-darken); }
.event-dot.interna { background-color: var(--mud-palette-success-darken); }
.event-dot.commessa { background-color: var(--mud-palette-warning); }
.calendar-day:hover .event-popup { display: block; }
.calendar-day-wrapper {
position: relative;
width: 100%;
height: 100%;
}
.radiusTopLeft { border-top-left-radius: 12px; }
.radiusTopRight { border-top-right-radius: 12px; }
.radiusBottomLeft { border-bottom-left-radius: 12px; }
.radiusBottomRight { border-bottom-right-radius: 12px; }
.activityContainer { margin-top: 1rem; }
.calendar-activity {
width: 100%;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
gap: 1rem;
overflow-y: auto;
overflow-x: hidden;
padding-bottom: 1rem;
}
.calendar-activity::-webkit-scrollbar { display: none; }
.calendar-activity {
-ms-overflow-style: none;
scrollbar-width: none;
}

View File

@@ -1,88 +0,0 @@
@using Template.Shared.Core.Dto
@using Template.Shared.Core.Interface
@using Template.Shared.Components.Layout.Spinner
@inject IManageDataService manageData
<div class="calendar">
@{
DateTime? currentDate = null;
}
@if (Load)
{
<SpinnerLayout FullScreen="false"/>
}
else
{
@if (!Activities.IsNullOrEmpty())
{
foreach (var activity in Activities!)
{
var dateToShow = activity.EffectiveDate ?? activity.EstimatedDate;
if (currentDate != dateToShow?.Date)
{
currentDate = dateToShow?.Date;
<div class="week-info">
<span>@($"{currentDate:D}")</span>
</div>
}
<ActivityCard Activity="activity"/>
}
}
else
{
<NoDataAvailable Text="Nessuna attività trovata" ImageSource="_content/Template.Shared/images/undraw_file-search_cbur.svg"/>
}
}
</div>
@code
{
[Parameter] public required DateRange Date { get; set; }
[Parameter] public EventCallback<DateRange> DateChanged { get; set; }
private List<ActivityDTO>? Activities { get; set; }
private bool Load { get; set; } = true;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await LoadData();
}
}
protected override async Task OnParametersSetAsync()
{
await LoadData();
}
private async Task LoadData()
{
Load = true;
StateHasChanged();
await Task.Delay(500);
var refreshActivity = await RefreshActivity();
Activities = refreshActivity;
Load = false;
StateHasChanged();
}
private async Task<List<ActivityDTO>> RefreshActivity()
{
var activityDto = await Task.Run(async () =>
{
return (await manageData.GetActivity(x =>
(x.EffectiveDate == null && x.EstimatedDate >= Date.Start && x.EstimatedDate <= Date.End) ||
(x.EffectiveDate >= Date.Start && x.EffectiveDate <= Date.End)
))
.OrderBy(x => x.EffectiveDate ?? x.EstimatedDate)
.ToList();
});
return activityDto;
}
}

View File

@@ -1,26 +0,0 @@
.calendar {
width: 100%;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
gap: 1rem;
overflow-y: auto;
overflow-x: hidden;
padding-bottom: 1rem;
}
.calendar::-webkit-scrollbar { display: none; }
.calendar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.week-info {
background: var(--mud-palette-action-disabled-background);
width: 100%;
padding: .3rem .5rem;
border-radius: 8px;
text-transform: capitalize;
font-weight: 700;
}

View File

@@ -1,8 +1,9 @@
@using Template.Shared.Core.Dto @using Template.Shared.Core.Dto
@using Template.Shared.Core.Entity
@using Template.Shared.Core.Helpers.Enum @using Template.Shared.Core.Helpers.Enum
@inject IDialogService Dialog @inject IDialogService Dialog
<div class="activity-card @Activity.Category.ConvertToHumanReadable()" @onclick="() => ModalHelpers.OpenActivityForm(Dialog, Activity.ActivityId)"> <div class="activity-card @Activity.Category.ConvertToHumanReadable()" @onclick="OpenActivity">
<div class="activity-left-section"> <div class="activity-left-section">
<div class="activity-body-section"> <div class="activity-body-section">
<div class="title-section"> <div class="title-section">
@@ -63,6 +64,7 @@
@code { @code {
[Parameter] public ActivityDTO Activity { get; set; } = new(); [Parameter] public ActivityDTO Activity { get; set; } = new();
[Parameter] public EventCallback<string> ActivityChanged { get; set; }
private TimeSpan? Durata { get; set; } private TimeSpan? Durata { get; set; }
@@ -75,4 +77,14 @@
_ => null _ => null
}; };
} }
private async Task OpenActivity()
{
var result = await ModalHelpers.OpenActivityForm(Dialog, Activity.ActivityId);
if (result is { Canceled: false, Data: not null } && result.Data.GetType() == typeof(StbActivity))
{
await ActivityChanged.InvokeAsync(((StbActivity)result.Data).ActivityId);
}
}
} }

View File

@@ -50,6 +50,6 @@
} }
.activity-info-section { .activity-info-section {
width: min-content;
display: flex; display: flex;
flex-wrap: wrap;
} }

View File

@@ -0,0 +1,172 @@
@using Template.Shared.Core.Dto
@using Template.Shared.Components.Layout
@using Template.Shared.Core.Entity
@using Template.Shared.Core.Interface
@using Template.Shared.Components.Layout.Overlay
@inject IManageDataService ManageData
@inject INetworkService NetworkService
@inject IIntegryApiService IntegryApiService
<MudDialog Class="customDialog-form">
<DialogContent>
<HeaderLayout Cancel="true" OnCancel="() => MudDialog.Cancel()" LabelSave="@LabelSave" OnSave="Save" ShowNotifications="false" Title="@(IsNew ? "Nuova" : $"{ActivityModel.ActivityId}")" />
<div class="content">
<div class="input-card">
<MudTextField ReadOnly="IsView" T="string?" Placeholder="Descrizione" Variant="Variant.Text" Lines="3" @bind-Value="ActivityModel.ActivityDescription" @bind-Value:after="OnAfterChangeValue" DebounceInterval="500" OnDebounceIntervalElapsed="OnAfterChangeValue" />
</div>
<div class="input-card">
<div class="form-container">
<MudInput ReadOnly="IsView" T="string?" Placeholder="Cliente" @bind-Value="ActivityModel.Cliente" @bind-Value:after="OnAfterChangeValue" />
</div>
<div class="divider"></div>
<div class="form-container">
<MudInput ReadOnly="IsView" T="string?" Placeholder="Commessa" @bind-Value="ActivityModel.Commessa" @bind-Value:after="OnAfterChangeValue" />
</div>
</div>
<div class="input-card">
<div class="form-container">
<span>Inizio</span>
<MudTextField ReadOnly="IsView" T="DateTime?" Format="yyyy-MM-ddTHH:mm" InputType="InputType.DateTimeLocal" @bind-Value="ActivityModel.EstimatedTime" @bind-Value:after="OnAfterChangeValue" DebounceInterval="500" OnDebounceIntervalElapsed="OnAfterChangeValue" />
</div>
<div class="divider"></div>
<div class="form-container">
<span>Fine</span>
<MudTextField ReadOnly="IsView" T="DateTime?" Format="yyyy-MM-ddTHH:mm" InputType="InputType.DateTimeLocal" @bind-Value="ActivityModel.EstimatedEndtime" @bind-Value:after="OnAfterChangeValue" DebounceInterval="500" OnDebounceIntervalElapsed="OnAfterChangeValue" />
</div>
<div class="divider"></div>
<div class="form-container">
<span>Avviso</span>
<MudSwitch ReadOnly="IsView" T="bool" Disabled="true" Color="Color.Primary" />
</div>
</div>
<div class="input-card">
<div class="form-container">
<span class="disable-full-width">Assegnata a</span>
<MudSelectExtended FullWidth="true" ReadOnly="IsView" T="string?" Variant="Variant.Text" @bind-Value="ActivityModel.UserName" @bind-Value:after="OnAfterChangeValue" Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var user in Users)
{
<MudSelectItemExtended Class="custom-item-select" Value="@user.UserName">@user.FullName</MudSelectItemExtended>
}
</MudSelectExtended>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Tipo</span>
<MudSelectExtended ReadOnly="IsView" FullWidth="true" T="string?" Variant="Variant.Text" @bind-Value="ActivityModel.ActivityTypeId" @bind-Value:after="OnAfterChangeValue" Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var type in ActivityType)
{
<MudSelectItemExtended Class="custom-item-select" Value="@type.ActivityTypeId">@type.ActivityTypeId</MudSelectItemExtended>
}
</MudSelectExtended>
</div>
<div class="divider"></div>
<div class="form-container">
<span class="disable-full-width">Esito</span>
<MudSelectExtended ReadOnly="IsView" FullWidth="true" T="string?" Variant="Variant.Text" @bind-Value="ActivityModel.ActivityResultId" @bind-Value:after="OnAfterChangeValue" Class="customIcon-select" AdornmentIcon="@Icons.Material.Filled.Code">
@foreach (var result in ActivityResult)
{
<MudSelectItemExtended Class="custom-item-select" Value="@result.ActivityResultId">@result.ActivityResultId</MudSelectItemExtended>
}
</MudSelectExtended>
</div>
</div>
<div class="input-card">
<MudTextField ReadOnly="IsView" T="string?" Placeholder="Note" Variant="Variant.Text" Lines="4" @bind-Value="ActivityModel.Note" @bind-Value:after="OnAfterChangeValue" DebounceInterval="500" OnDebounceIntervalElapsed="OnAfterChangeValue" />
</div>
</div>
</DialogContent>
</MudDialog>
<SaveOverlay VisibleOverlay="VisibleOverlay" SuccessAnimation="SuccessAnimation" />
@code {
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; }
[Parameter] public string? Id { get; set; }
private ActivityDTO OriginalModel { get; set; } = new();
private ActivityDTO ActivityModel { get; set; } = new();
private List<StbActivityResult> ActivityResult { get; set; } = [];
private List<StbActivityType> ActivityType { get; set; } = [];
private List<StbUser> Users { get; set; } = [];
private bool IsNew => Id.IsNullOrEmpty();
private bool IsView => !IsNew && !NetworkService.IsNetworkAvailable();
private string? LabelSave { get; set; }
//Overlay for save
private bool VisibleOverlay { get; set; }
private bool SuccessAnimation { get; set; }
protected override async Task OnInitializedAsync()
{
_ = LoadData();
LabelSave = IsNew ? "Aggiungi" : null;
if (!Id.IsNullOrEmpty())
ActivityModel = (await ManageData.GetActivity(x => x.ActivityId.Equals(Id))).Last();
if (IsNew)
{
ActivityModel.EstimatedTime = DateTime.Today.Add(TimeSpan.FromHours(DateTime.Now.Hour));
ActivityModel.EstimatedEndtime = DateTime.Today.Add(TimeSpan.FromHours(DateTime.Now.Hour) + TimeSpan.FromHours(1));
}
OriginalModel = ActivityModel.Clone();
}
private async Task Save()
{
VisibleOverlay = true;
StateHasChanged();
var newActivity = await IntegryApiService.SaveActivity(ActivityModel);
await ManageData.InsertOrUpdate(newActivity);
SuccessAnimation = true;
StateHasChanged();
await Task.Delay(1250);
MudDialog.Close(newActivity);
}
private async Task LoadData()
{
Users = await ManageData.GetTable<StbUser>();
ActivityResult = await ManageData.GetTable<StbActivityResult>();
ActivityType = await ManageData.GetTable<StbActivityType>(x => x.FlagTipologia.Equals("A"));
}
private void OnAfterChangeValue()
{
LabelSave = !OriginalModel.Equals(ActivityModel) ? "Aggiorna" : null;
StateHasChanged();
}
}

View File

@@ -10,88 +10,89 @@ public class ActivityDTO : StbActivity
public ActivityCategoryEnum Category { get; set; } public ActivityCategoryEnum Category { get; set; }
public bool Complete { get; set; } public bool Complete { get; set; }
private sealed class ActivityDtoEqualityComparer : IEqualityComparer<ActivityDTO>
{
public bool Equals(ActivityDTO? x, ActivityDTO? y)
{
if (ReferenceEquals(x, y)) return true;
if (x is null) return false;
if (y is null) return false;
if (x.GetType() != y.GetType()) return false;
return x.ActivityId == y.ActivityId && x.ActivityResultId == y.ActivityResultId && x.ActivityTypeId == y.ActivityTypeId && x.DataInsAct.Equals(y.DataInsAct) && x.ActivityDescription == y.ActivityDescription && x.ParentActivityId == y.ParentActivityId && x.TipoAnag == y.TipoAnag && x.CodAnag == y.CodAnag && x.CodJcom == y.CodJcom && x.CodJfas == y.CodJfas && Nullable.Equals(x.EstimatedDate, y.EstimatedDate) && Nullable.Equals(x.EstimatedTime, y.EstimatedTime) && Nullable.Equals(x.AlarmDate, y.AlarmDate) && Nullable.Equals(x.AlarmTime, y.AlarmTime) && Nullable.Equals(x.EffectiveDate, y.EffectiveDate) && Nullable.Equals(x.EffectiveTime, y.EffectiveTime) && x.ResultDescription == y.ResultDescription && Nullable.Equals(x.EstimatedEnddate, y.EstimatedEnddate) && Nullable.Equals(x.EstimatedEndtime, y.EstimatedEndtime) && Nullable.Equals(x.EffectiveEnddate, y.EffectiveEnddate) && Nullable.Equals(x.EffectiveEndtime, y.EffectiveEndtime) && x.UserCreator == y.UserCreator && x.UserName == y.UserName && Nullable.Equals(x.PercComp, y.PercComp) && Nullable.Equals(x.EstimatedHours, y.EstimatedHours) && x.CodMart == y.CodMart && x.PartitaMag == y.PartitaMag && x.Matricola == y.Matricola && x.Priorita == y.Priorita && Nullable.Equals(x.ActivityPlayCounter, y.ActivityPlayCounter) && x.ActivityEvent == y.ActivityEvent && x.Guarantee == y.Guarantee && x.Note == y.Note && x.Rfid == y.Rfid && x.IdLotto == y.IdLotto && x.PersonaRif == y.PersonaRif && x.HrNum == y.HrNum && x.Gestione == y.Gestione && Nullable.Equals(x.DataOrd, y.DataOrd) && x.NumOrd == y.NumOrd && x.IdStep == y.IdStep && x.IdRiga == y.IdRiga && Nullable.Equals(x.OraInsAct, y.OraInsAct) && x.IndiceGradimento == y.IndiceGradimento && x.NoteGradimento == y.NoteGradimento && x.FlagRisolto == y.FlagRisolto && x.FlagTipologia == y.FlagTipologia && x.OreRapportino == y.OreRapportino && x.UserModifier == y.UserModifier && Nullable.Equals(x.OraModAct, y.OraModAct) && Nullable.Equals(x.OraViewAct, y.OraViewAct) && x.CodVdes == y.CodVdes && x.CodCmac == y.CodCmac && x.WrikeId == y.WrikeId && x.CodMgrp == y.CodMgrp && x.PlanId == y.PlanId && x.Commessa == y.Commessa && x.Cliente == y.Cliente && x.Category == y.Category && x.Complete == y.Complete;
}
public int GetHashCode(ActivityDTO obj)
{
var hashCode = new HashCode();
hashCode.Add(obj.ActivityId);
hashCode.Add(obj.ActivityResultId);
hashCode.Add(obj.ActivityTypeId);
hashCode.Add(obj.DataInsAct);
hashCode.Add(obj.ActivityDescription);
hashCode.Add(obj.ParentActivityId);
hashCode.Add(obj.TipoAnag);
hashCode.Add(obj.CodAnag);
hashCode.Add(obj.CodJcom);
hashCode.Add(obj.CodJfas);
hashCode.Add(obj.EstimatedDate);
hashCode.Add(obj.EstimatedTime);
hashCode.Add(obj.AlarmDate);
hashCode.Add(obj.AlarmTime);
hashCode.Add(obj.EffectiveDate);
hashCode.Add(obj.EffectiveTime);
hashCode.Add(obj.ResultDescription);
hashCode.Add(obj.EstimatedEnddate);
hashCode.Add(obj.EstimatedEndtime);
hashCode.Add(obj.EffectiveEnddate);
hashCode.Add(obj.EffectiveEndtime);
hashCode.Add(obj.UserCreator);
hashCode.Add(obj.UserName);
hashCode.Add(obj.PercComp);
hashCode.Add(obj.EstimatedHours);
hashCode.Add(obj.CodMart);
hashCode.Add(obj.PartitaMag);
hashCode.Add(obj.Matricola);
hashCode.Add(obj.Priorita);
hashCode.Add(obj.ActivityPlayCounter);
hashCode.Add(obj.ActivityEvent);
hashCode.Add(obj.Guarantee);
hashCode.Add(obj.Note);
hashCode.Add(obj.Rfid);
hashCode.Add(obj.IdLotto);
hashCode.Add(obj.PersonaRif);
hashCode.Add(obj.HrNum);
hashCode.Add(obj.Gestione);
hashCode.Add(obj.DataOrd);
hashCode.Add(obj.NumOrd);
hashCode.Add(obj.IdStep);
hashCode.Add(obj.IdRiga);
hashCode.Add(obj.OraInsAct);
hashCode.Add(obj.IndiceGradimento);
hashCode.Add(obj.NoteGradimento);
hashCode.Add(obj.FlagRisolto);
hashCode.Add(obj.FlagTipologia);
hashCode.Add(obj.OreRapportino);
hashCode.Add(obj.UserModifier);
hashCode.Add(obj.OraModAct);
hashCode.Add(obj.OraViewAct);
hashCode.Add(obj.CodVdes);
hashCode.Add(obj.CodCmac);
hashCode.Add(obj.WrikeId);
hashCode.Add(obj.CodMgrp);
hashCode.Add(obj.PlanId);
hashCode.Add(obj.Commessa);
hashCode.Add(obj.Cliente);
hashCode.Add((int)obj.Category);
hashCode.Add(obj.Complete);
return hashCode.ToHashCode();
}
}
public static IEqualityComparer<ActivityDTO> ActivityDtoComparer { get; } = new ActivityDtoEqualityComparer();
public ActivityDTO Clone() public ActivityDTO Clone()
{ {
return (ActivityDTO)MemberwiseClone(); return (ActivityDTO)MemberwiseClone();
} }
private bool Equals(ActivityDTO other)
{
return Commessa == other.Commessa &&
Cliente == other.Cliente &&
Category == other.Category &&
Complete == other.Complete && ActivityId == other.ActivityId && ActivityResultId == other.ActivityResultId && ActivityTypeId == other.ActivityTypeId && DataInsAct.Equals(other.DataInsAct) && ActivityDescription == other.ActivityDescription && ParentActivityId == other.ParentActivityId && TipoAnag == other.TipoAnag && CodAnag == other.CodAnag && CodJcom == other.CodJcom && CodJfas == other.CodJfas && Nullable.Equals(EstimatedDate, other.EstimatedDate) && Nullable.Equals(EstimatedTime, other.EstimatedTime) && Nullable.Equals(AlarmDate, other.AlarmDate) && Nullable.Equals(AlarmTime, other.AlarmTime) && Nullable.Equals(EffectiveDate, other.EffectiveDate) && Nullable.Equals(EffectiveTime, other.EffectiveTime) && ResultDescription == other.ResultDescription && Nullable.Equals(EstimatedEnddate, other.EstimatedEnddate) && Nullable.Equals(EstimatedEndtime, other.EstimatedEndtime) && Nullable.Equals(EffectiveEnddate, other.EffectiveEnddate) && Nullable.Equals(EffectiveEndtime, other.EffectiveEndtime) && UserCreator == other.UserCreator && UserName == other.UserName && Nullable.Equals(PercComp, other.PercComp) && Nullable.Equals(EstimatedHours, other.EstimatedHours) && CodMart == other.CodMart && PartitaMag == other.PartitaMag && Matricola == other.Matricola && Priorita == other.Priorita && Nullable.Equals(ActivityPlayCounter, other.ActivityPlayCounter) && ActivityEvent == other.ActivityEvent && Guarantee == other.Guarantee && Note == other.Note && Rfid == other.Rfid && IdLotto == other.IdLotto && PersonaRif == other.PersonaRif && HrNum == other.HrNum && Gestione == other.Gestione && Nullable.Equals(DataOrd, other.DataOrd) && NumOrd == other.NumOrd && IdStep == other.IdStep && IdRiga == other.IdRiga && Nullable.Equals(OraInsAct, other.OraInsAct) && IndiceGradimento == other.IndiceGradimento && NoteGradimento == other.NoteGradimento && FlagRisolto == other.FlagRisolto && FlagTipologia == other.FlagTipologia && OreRapportino == other.OreRapportino && UserModifier == other.UserModifier && Nullable.Equals(OraModAct, other.OraModAct) && Nullable.Equals(OraViewAct, other.OraViewAct) && CodVdes == other.CodVdes && CodCmac == other.CodCmac && WrikeId == other.WrikeId && CodMgrp == other.CodMgrp && PlanId == other.PlanId;
}
public override bool Equals(object? obj)
{
if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == GetType() && Equals((ActivityDTO)obj);
}
public override int GetHashCode()
{
var hashCode = new HashCode();
hashCode.Add(ActivityId);
hashCode.Add(ActivityResultId);
hashCode.Add(ActivityTypeId);
hashCode.Add(DataInsAct);
hashCode.Add(ActivityDescription);
hashCode.Add(ParentActivityId);
hashCode.Add(TipoAnag);
hashCode.Add(CodAnag);
hashCode.Add(CodJcom);
hashCode.Add(CodJfas);
hashCode.Add(EstimatedDate);
hashCode.Add(EstimatedTime);
hashCode.Add(AlarmDate);
hashCode.Add(AlarmTime);
hashCode.Add(EffectiveDate);
hashCode.Add(EffectiveTime);
hashCode.Add(ResultDescription);
hashCode.Add(EstimatedEnddate);
hashCode.Add(EstimatedEndtime);
hashCode.Add(EffectiveEnddate);
hashCode.Add(EffectiveEndtime);
hashCode.Add(UserCreator);
hashCode.Add(UserName);
hashCode.Add(PercComp);
hashCode.Add(EstimatedHours);
hashCode.Add(CodMart);
hashCode.Add(PartitaMag);
hashCode.Add(Matricola);
hashCode.Add(Priorita);
hashCode.Add(ActivityPlayCounter);
hashCode.Add(ActivityEvent);
hashCode.Add(Guarantee);
hashCode.Add(Note);
hashCode.Add(Rfid);
hashCode.Add(IdLotto);
hashCode.Add(PersonaRif);
hashCode.Add(HrNum);
hashCode.Add(Gestione);
hashCode.Add(DataOrd);
hashCode.Add(NumOrd);
hashCode.Add(IdStep);
hashCode.Add(IdRiga);
hashCode.Add(OraInsAct);
hashCode.Add(IndiceGradimento);
hashCode.Add(NoteGradimento);
hashCode.Add(FlagRisolto);
hashCode.Add(FlagTipologia);
hashCode.Add(OreRapportino);
hashCode.Add(UserModifier);
hashCode.Add(OraModAct);
hashCode.Add(OraViewAct);
hashCode.Add(CodVdes);
hashCode.Add(CodCmac);
hashCode.Add(WrikeId);
hashCode.Add(CodMgrp);
hashCode.Add(PlanId);
hashCode.Add(Commessa);
hashCode.Add(Cliente);
hashCode.Add(Category);
hashCode.Add(Complete);
return hashCode.ToHashCode();
}
} }

View File

@@ -1,6 +0,0 @@
namespace Template.Shared.Core.Dto;
public class ActivityResultDTO
{
public string ActivityResultId { get; set; }
}

View File

@@ -0,0 +1,20 @@
using Template.Shared.Core.Helpers;
using Template.Shared.Core.Helpers.Enum;
namespace Template.Shared.Core.Dto;
public class FilterActivityDTO
{
public string? Text { get; set; }
public IEnumerable<string>? User { get; set; }
public string? Type { get; set; }
public string? Result { get; set; }
public ActivityCategoryEnum? Category { get; set; }
public bool ClearFilter =>
Text.IsNullOrEmpty() &&
User.IsNullOrEmpty() &&
Type.IsNullOrEmpty() &&
Result.IsNullOrEmpty() &&
Category == null;
}

View File

@@ -0,0 +1,16 @@
using System.Text.Json.Serialization;
using Template.Shared.Core.Entity;
namespace Template.Shared.Core.Dto;
public class SettingsResponseDTO
{
[JsonPropertyName("activityTypes")]
public List<StbActivityType>? ActivityTypes { get; set; }
[JsonPropertyName("activityResults")]
public List<StbActivityResult>? ActivityResults { get; set; }
[JsonPropertyName("stbUsers")]
public List<StbUser>? StbUsers { get; set; }
}

View File

@@ -0,0 +1,32 @@
using SQLite;
using System.Text.Json.Serialization;
namespace Template.Shared.Core.Entity;
[Table("stb_activity_result")]
public class StbActivityResult
{
[PrimaryKey, Column("activity_result_id"), JsonPropertyName("activityResultId")]
public string ActivityResultId { get; set; }
[Column("path_icona"), JsonPropertyName("pathIcona")]
public string? PathIcona { get; set; }
[Column("flag_save_rap_lav"), JsonPropertyName("flagSaveRapLav")]
public string FlagSaveRapLav { get; set; } = "N";
[Column("flag_activity_result"), JsonPropertyName("flagActivityResult")]
public int? FlagActivityResult { get; set; } = 1;
[Column("flag_insert_activity"), JsonPropertyName("flagInsertActivity")]
public string FlagInsertActivity { get; set; } = "N";
[Column("flag_attivo"), JsonPropertyName("flagAttivo")]
public string FlagAttivo { get; set; } = "S";
[Column("flag_invio_notifica"), JsonPropertyName("flagInvioNotifica")]
public string FlagInvioNotifica { get; set; } = "N";
[Column("flag_stato_attivita"), JsonPropertyName("flagStatoAttivita")]
public string FlagStatoAttivita { get; set; } = "N";
}

View File

@@ -0,0 +1,41 @@
using SQLite;
using System.Text.Json.Serialization;
namespace Template.Shared.Core.Entity;
[Table("stb_activity_type")]
public class StbActivityType
{
[Column("activity_type_id"), JsonPropertyName("activityTypeId"), Indexed(Name = "ActivityTypePK", Order = 1, Unique = true)]
public string ActivityTypeId { get; set; }
[Column("flag_tipologia"), JsonPropertyName("flagTipologia"), Indexed(Name = "ActivityTypePK", Order = 2, Unique = true)]
public string FlagTipologia { get; set; }
[Column("estimated_duration"), JsonPropertyName("estimatedDuration")]
public double? EstimatedDuration { get; set; } = 0;
[Column("link_gest"), JsonPropertyName("linkGest")]
public string? LinkGest { get; set; }
[Column("cod_jfas"), JsonPropertyName("codJfas")]
public string? CodJfas { get; set; }
[Column("user_name"), JsonPropertyName("userName")]
public string? UserName { get; set; }
[Column("flag_sal"), JsonPropertyName("flagSal")]
public string FlagSal { get; set; } = "N";
[Column("flag_set_alarm"), JsonPropertyName("flagSetAlarm")]
public string FlagSetAlarm { get; set; } = "N";
[Column("flag_attiva"), JsonPropertyName("flagAttiva")]
public string FlagAttiva { get; set; } = "S";
[Column("flag_generate_mov"), JsonPropertyName("flagGenerateMov")]
public string FlagGenerateMov { get; set; } = "S";
[Column("flag_view_calendar"), JsonPropertyName("flagViewCalendar")]
public bool FlagViewCalendar { get; set; }
}

View File

@@ -0,0 +1,14 @@
using SQLite;
using System.Text.Json.Serialization;
namespace Template.Shared.Core.Entity;
[Table("stb_user")]
public class StbUser
{
[PrimaryKey, Column("user_name"), JsonPropertyName("userName")]
public string UserName { get; set; }
[Column("full_name"), JsonPropertyName("fullName")]
public string FullName { get; set; }
}

View File

@@ -4,14 +4,21 @@ namespace Template.Shared.Core.Helpers;
public static class ActivityCategoryHelper public static class ActivityCategoryHelper
{ {
public static string ConvertToHumanReadable(this ActivityCategoryEnum activityType) public static string ConvertToHumanReadable(this ActivityCategoryEnum activityCategory)
{ {
return activityType switch return activityCategory switch
{ {
ActivityCategoryEnum.Memo => "memo", ActivityCategoryEnum.Memo => "memo",
ActivityCategoryEnum.Interna => "interna", ActivityCategoryEnum.Interna => "interna",
ActivityCategoryEnum.Commessa => "commessa", ActivityCategoryEnum.Commessa => "commessa",
_ => throw new ArgumentOutOfRangeException(nameof(activityType), activityType, null) _ => throw new ArgumentOutOfRangeException(nameof(activityCategory), activityCategory, null)
}; };
} }
public static List<ActivityCategoryEnum> AllActivityCategory =>
[
ActivityCategoryEnum.Memo,
ActivityCategoryEnum.Interna,
ActivityCategoryEnum.Commessa
];
} }

View File

@@ -1,6 +0,0 @@
namespace Template.Shared.Core.Helpers.Enum;
public enum ActivityStatusEnum
{
}

View File

@@ -1,16 +1,17 @@
using MudBlazor; using MudBlazor;
using Template.Shared.Components.Pages; using Template.Shared.Components.SingleElements.Modal;
namespace Template.Shared.Core.Helpers; namespace Template.Shared.Core.Helpers;
public class ModalHelpers public class ModalHelpers
{ {
public static Task OpenActivityForm(IDialogService dialog ,string? id = null) => public static async Task<DialogResult?> OpenActivityForm(IDialogService dialog, string? id = null)
dialog.ShowAsync<ActivityForm>( {
var modal = await dialog.ShowAsync<ActivityForm>(
"Activity form", "Activity form",
new DialogParameters<ActivityForm> new DialogParameters<ActivityForm>
{ {
{ x => x.Id, id} { x => x.Id, id }
}, },
new DialogOptions new DialogOptions
{ {
@@ -19,4 +20,7 @@ public class ModalHelpers
NoHeader = true NoHeader = true
} }
); );
return await modal.Result;
}
} }

View File

@@ -10,4 +10,10 @@ public static class ObjectExtensions
public static bool IsNullOrEmpty(this string? obj) => public static bool IsNullOrEmpty(this string? obj) =>
string.IsNullOrEmpty(obj); string.IsNullOrEmpty(obj);
}
public static bool EqualsIgnoreCase(this string obj, string anotherString) =>
string.Equals(obj, anotherString, StringComparison.OrdinalIgnoreCase);
public static bool ContainsIgnoreCase(this string obj, string anotherString) =>
obj.Contains(anotherString, StringComparison.OrdinalIgnoreCase);
}

View File

@@ -5,8 +5,11 @@ namespace Template.Shared.Core.Interface;
public interface IIntegryApiService public interface IIntegryApiService
{ {
Task<List<StbActivity>?> GetActivity(string? dateFilter = null); Task<List<StbActivity>?> RetrieveActivity(string? dateFilter = null);
Task<List<JtbComt>?> GetAllCommesse(string? dateFilter = null); Task<List<JtbComt>?> RetrieveAllCommesse(string? dateFilter = null);
Task<TaskSyncResponseDTO> GetAnagClie(string? dateFilter = null); Task<TaskSyncResponseDTO> RetrieveAnagClie(string? dateFilter = null);
Task<TaskSyncResponseDTO> GetProspect(string? dateFilter = null); Task<TaskSyncResponseDTO> RetrieveProspect(string? dateFilter = null);
Task<SettingsResponseDTO> RetrieveSettings();
Task<StbActivity?> SaveActivity(ActivityDTO activity);
} }

View File

@@ -6,15 +6,10 @@ namespace Template.Shared.Core.Interface;
public interface IManageDataService public interface IManageDataService
{ {
Task<List<AnagClie>> GetAnagClie(Expression<Func<AnagClie, bool>>? whereCond = null); Task<List<T>> GetTable<T>(Expression<Func<T, bool>>? whereCond = null) where T : new();
Task<List<JtbComt>> GetJtbComt(Expression<Func<JtbComt, bool>>? whereCond = null);
Task<List<PtbPros>> GetPtbPros(Expression<Func<PtbPros, bool>>? whereCond = null);
Task<List<PtbProsRif>> GetPtbProsRif(Expression<Func<PtbProsRif, bool>>? whereCond = null);
Task<List<StbActivity>> GetStbActivity(Expression<Func<StbActivity, bool>>? whereCond = null);
Task<List<VtbCliePersRif>> GetVtbCliePersRif(Expression<Func<VtbCliePersRif, bool>>? whereCond = null);
Task<List<VtbDest>> GetVtbDest(Expression<Func<VtbDest, bool>>? whereCond = null);
Task<List<ActivityDTO>> GetActivity(Expression<Func<StbActivity, bool>>? whereCond = null); Task<List<ActivityDTO>> GetActivity(Expression<Func<StbActivity, bool>>? whereCond = null);
Task InsertOrUpdate<T>(T objectToSave);
Task ClearDb(); Task ClearDb();
} }

View File

@@ -6,4 +6,5 @@ public interface ISyncDbService
Task GetAndSaveCommesse(string? dateFilter = null); Task GetAndSaveCommesse(string? dateFilter = null);
Task GetAndSaveProspect(string? dateFilter = null); Task GetAndSaveProspect(string? dateFilter = null);
Task GetAndSaveClienti(string? dateFilter = null); Task GetAndSaveClienti(string? dateFilter = null);
Task GetAndSaveSettings(string? dateFilter = null);
} }

View File

@@ -9,14 +9,14 @@ namespace Template.Shared.Core.Services;
public class IntegryApiService(IIntegryApiRestClient integryApiRestClient, IUserSession userSession) public class IntegryApiService(IIntegryApiRestClient integryApiRestClient, IUserSession userSession)
: IIntegryApiService : IIntegryApiService
{ {
public Task<List<StbActivity>?> GetActivity(string? dateFilter) public Task<List<StbActivity>?> RetrieveActivity(string? dateFilter)
{ {
var queryParams = new Dictionary<string, object> { { "dateFilter", dateFilter ?? "2020-01-01" } }; var queryParams = new Dictionary<string, object> { { "dateFilter", dateFilter ?? "2020-01-01" } };
return integryApiRestClient.AuthorizedGet<List<StbActivity>?>("getActivityCrm", queryParams); return integryApiRestClient.AuthorizedGet<List<StbActivity>?>("crm/retrieveActivity", queryParams);
} }
public Task<List<JtbComt>?> GetAllCommesse(string? dateFilter) public Task<List<JtbComt>?> RetrieveAllCommesse(string? dateFilter)
{ {
var queryParams = new Dictionary<string, object>(); var queryParams = new Dictionary<string, object>();
@@ -25,10 +25,10 @@ public class IntegryApiService(IIntegryApiRestClient integryApiRestClient, IUser
queryParams.Add("dateFilter", dateFilter); queryParams.Add("dateFilter", dateFilter);
} }
return integryApiRestClient.AuthorizedGet<List<JtbComt>?>("getCommesseCrm", queryParams); return integryApiRestClient.AuthorizedGet<List<JtbComt>?>("crm/retrieveCommesse", queryParams);
} }
public Task<TaskSyncResponseDTO> GetAnagClie(string? dateFilter) public Task<TaskSyncResponseDTO> RetrieveAnagClie(string? dateFilter)
{ {
var queryParams = new Dictionary<string, object>(); var queryParams = new Dictionary<string, object>();
@@ -37,10 +37,10 @@ public class IntegryApiService(IIntegryApiRestClient integryApiRestClient, IUser
queryParams.Add("dateFilter", dateFilter); queryParams.Add("dateFilter", dateFilter);
} }
return integryApiRestClient.AuthorizedGet<TaskSyncResponseDTO>("getAnagClieCrm", queryParams)!; return integryApiRestClient.AuthorizedGet<TaskSyncResponseDTO>("crm/retrieveClienti", queryParams)!;
} }
public Task<TaskSyncResponseDTO> GetProspect(string? dateFilter) public Task<TaskSyncResponseDTO> RetrieveProspect(string? dateFilter)
{ {
var queryParams = new Dictionary<string, object>(); var queryParams = new Dictionary<string, object>();
@@ -49,6 +49,12 @@ public class IntegryApiService(IIntegryApiRestClient integryApiRestClient, IUser
queryParams.Add("dateFilter", dateFilter); queryParams.Add("dateFilter", dateFilter);
} }
return integryApiRestClient.AuthorizedGet<TaskSyncResponseDTO>("getProspectCrm", queryParams)!; return integryApiRestClient.AuthorizedGet<TaskSyncResponseDTO>("crm/retrieveProspect", queryParams)!;
} }
public Task<SettingsResponseDTO> RetrieveSettings() =>
integryApiRestClient.AuthorizedGet<SettingsResponseDTO>("crm/retrieveSettings", null)!;
public Task<StbActivity?> SaveActivity(ActivityDTO activity) =>
integryApiRestClient.AuthorizedPost<StbActivity?>("crm/saveActivity", activity);
} }

View File

@@ -131,7 +131,54 @@ h1:focus { outline: none; }
.flex-column, .navbar-brand { padding-left: env(safe-area-inset-left); } .flex-column, .navbar-brand { padding-left: env(safe-area-inset-left); }
} }
/*Spinner*/
.spinner-container {
display: flex;
justify-content: center;
height: 100vh;
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-secondary);
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)
}
}
/*MudBlazor Personalization*/ /*MudBlazor Personalization*/
.mud-button-group-horizontal:not(.mud-button-group-rtl) > .mud-button-root:not(:last-child), .mud-button-group-horizontal:not(.mud-button-group-rtl) > :not(:last-child) .mud-button-root { .mud-button-group-horizontal:not(.mud-button-group-rtl) > .mud-button-root:not(:last-child), .mud-button-group-horizontal:not(.mud-button-group-rtl) > :not(:last-child) .mud-button-root {
border-top-right-radius: 0 !important; border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important; border-bottom-right-radius: 0 !important;
@@ -145,4 +192,44 @@ h1:focus { outline: none; }
.customDialog-form .mud-dialog-content { .customDialog-form .mud-dialog-content {
padding: 0 .75rem; padding: 0 .75rem;
margin: 0; margin: 0;
}
.custom-item-select {
padding: 6px 16px;
}
.custom-item-select .mud-typography-body1 {
font-weight: 600;
font-size: .9rem;
}
@supports (-webkit-touch-callout: none) {
.status-bar-safe-area {
display: flex;
position: fixed;
top: 0;
height: env(safe-area-inset-top);
background-color: #f7f7f7;
width: 100%;
z-index: 1;
background-color: var(--primary-color);
}
.modal {
padding-top: env(safe-area-inset-top);
}
article {
padding-top: 3rem !important;
padding-bottom: calc(7rem + env(safe-area-inset-bottom)) !important;
}
#app {
padding-top: env(safe-area-inset-top);
height: 100vh;
}
.flex-column, .navbar-brand {
padding-left: env(safe-area-inset-left);
}
} }

View File

@@ -5,4 +5,5 @@
/*Utility*/ /*Utility*/
--card-shadow: 5px 5px 10px 0 var(--gray-for-shadow); --card-shadow: 5px 5px 10px 0 var(--gray-for-shadow);
--custom-box-shadow: 1px 2px 5px rgba(165, 165, 165, 0.5); --custom-box-shadow: 1px 2px 5px rgba(165, 165, 165, 0.5);
} --mud-default-borderradius: 12px !important;
}

View File

@@ -0,0 +1,80 @@
.title {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
}
.customDialog-form .content {
height: calc(100vh - (.6rem + 40px));
overflow: auto;
-ms-overflow-style: none;
scrollbar-width: none;
}
.customDialog-form .header { padding: 0 !important; }
.customDialog-form .content::-webkit-scrollbar { display: none; }
.input-card {
width: 100%;
background: var(--mud-palette-background-gray);
border-radius: 9px;
padding: .5rem 1rem;
margin-bottom: 1.5rem;
}
.input-card.clearButton {
display: flex;
align-items: center;
justify-content: space-between;
padding: .4rem 1rem !important;
}
.input-card > .divider { margin: 0 !important; }
.form-container {
display: flex;
justify-content: space-between;
align-items: center;
min-height: 35px;
}
.form-container > span {
font-weight: 600;
width: 50%;
margin-right: .3rem;
}
.form-container > .disable-full-width { width: unset !important; }
.dateTime-picker {
display: flex;
gap: .3rem;
flex-direction: row;
align-items: center;
}
/*Custom mudBlazor*/
.form-container .mud-input.mud-input-underline:before { border-bottom: none !important; }
.form-container .mud-input.mud-input-underline:after { border-bottom: none !important; }
.form-container.text-align-end .mud-input-slot { text-align: end; }
.input-card .mud-input.mud-input-underline:before { border-bottom: none !important; }
.input-card .mud-input.mud-input-underline:after { border-bottom: none !important; }
.form-container .customIcon-select .mud-icon-root.mud-svg-icon {
rotate: 90deg !important;
font-size: 1.1rem;
}
.form-container .customIcon-select .mud-input-slot { text-align: end; }
.input-card .mud-input {
width: 100%;
font-weight: 500;
}

View File

@@ -7,37 +7,7 @@ namespace Template.Web.Core.Services;
public class ManageDataService : IManageDataService public class ManageDataService : IManageDataService
{ {
public Task<List<AnagClie>> GetAnagClie(Expression<Func<AnagClie, bool>>? whereCond = null) public Task<List<T>> GetTable<T>(Expression<Func<T, bool>>? whereCond = null) where T : new()
{
throw new NotImplementedException();
}
public Task<List<JtbComt>> GetJtbComt(Expression<Func<JtbComt, bool>>? whereCond = null)
{
throw new NotImplementedException();
}
public Task<List<PtbPros>> GetPtbPros(Expression<Func<PtbPros, bool>>? whereCond = null)
{
throw new NotImplementedException();
}
public Task<List<PtbProsRif>> GetPtbProsRif(Expression<Func<PtbProsRif, bool>>? whereCond = null)
{
throw new NotImplementedException();
}
public Task<List<StbActivity>> GetStbActivity(Expression<Func<StbActivity, bool>>? whereCond = null)
{
throw new NotImplementedException();
}
public Task<List<VtbCliePersRif>> GetVtbCliePersRif(Expression<Func<VtbCliePersRif, bool>>? whereCond = null)
{
throw new NotImplementedException();
}
public Task<List<VtbDest>> GetVtbDest(Expression<Func<VtbDest, bool>>? whereCond = null)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@@ -47,6 +17,11 @@ public class ManageDataService : IManageDataService
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task InsertOrUpdate<T>(T objectToSave)
{
throw new NotImplementedException();
}
public Task ClearDb() public Task ClearDb()
{ {
throw new NotImplementedException(); throw new NotImplementedException();

View File

@@ -23,4 +23,9 @@ public class SyncDbService : ISyncDbService
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task GetAndSaveSettings(string? dateFilter = null)
{
throw new NotImplementedException();
}
} }