Cambiata visualizzazione calendario e aggiunto formAttività
This commit is contained in:
@@ -1,19 +1,26 @@
|
||||
@using ConSegna.Shared.Core.Helpers
|
||||
@using Template.Shared.Core.Dto
|
||||
@using Template.Shared.Core.Dto
|
||||
@using Template.Shared.Core.Interface
|
||||
@using Template.Shared.Components.Layout.Spinner
|
||||
@inject IManageDataService manageData
|
||||
|
||||
<div class="calendar">
|
||||
@if (!Activities.IsNullOrEmpty())
|
||||
@if (Load)
|
||||
{
|
||||
@foreach (var activity in Activities!)
|
||||
{
|
||||
<ActivityCard Activity="activity"/>
|
||||
}
|
||||
<SpinnerLayout FullScreen="false" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<NoDataAvailable Text="Nessuna attività trovata" ImageSource="_content/Template.Shared/images/undraw_file-search_cbur.svg"/>
|
||||
@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>
|
||||
|
||||
@@ -23,7 +30,8 @@
|
||||
[Parameter] public required DateTime? Date { get; set; }
|
||||
[Parameter] public EventCallback<DateTime?> DateChanged { get; set; }
|
||||
|
||||
private List<ActivityDTO>? Activities { get; set; } = null;
|
||||
private List<ActivityDTO>? Activities { get; set; }
|
||||
private bool Load { get; set; } = true;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
@@ -40,9 +48,13 @@
|
||||
|
||||
private async Task LoadData()
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
Load = true;
|
||||
StateHasChanged();
|
||||
|
||||
await Task.Delay(500);
|
||||
var refreshActivity = await RefreshActivity();
|
||||
Activities = refreshActivity;
|
||||
Load = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
.calendar::-webkit-scrollbar { display: none; }
|
||||
|
||||
|
||||
.calendar {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
|
||||
@@ -1,42 +1,67 @@
|
||||
<div class="calendar">
|
||||
@foreach (var nomeGiorno in _giorniSettimana)
|
||||
{
|
||||
<div class="calendar-header">@nomeGiorno</div>
|
||||
}
|
||||
@using Template.Shared.Core.Dto
|
||||
@using Template.Shared.Core.Interface
|
||||
@inject IManageDataService manageData
|
||||
|
||||
@for (var i = 0; i < StartDays; i++)
|
||||
{
|
||||
<div class="calendar-day disabled @(i == 0 ? "radiusTopLeft" : "")"></div>
|
||||
}
|
||||
<div class="calendar-activity">
|
||||
<div class="calendar">
|
||||
@foreach (var nomeGiorno in _giorniSettimana)
|
||||
{
|
||||
<div class="calendar-header">@nomeGiorno</div>
|
||||
}
|
||||
|
||||
@for (var day = 1; day <= DaysInMonth; day++)
|
||||
{
|
||||
var currentDate = new DateTime(Date.Year, Date.Month, day);
|
||||
var events = GetEventsForDay(currentDate);
|
||||
var isToday = currentDate == DateTime.Today;
|
||||
@for (var i = 0; i < StartDays; i++)
|
||||
{
|
||||
<div class="calendar-day disabled @(i == 0 ? "radiusTopLeft" : "")"></div>
|
||||
}
|
||||
|
||||
var topRight = StartDays == 0 ? 7 : 7 - StartDays;
|
||||
var bottomLeft = DaysInMonth - (6 - EndDays);
|
||||
@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;
|
||||
|
||||
<div class="calendar-day @(isToday ? "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"></div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@for (var i = 0; i < EndDays; i++)
|
||||
{
|
||||
<div class="calendar-day disabled @(i + 1 == EndDays ? "radiusBottomRight" : "")"></div>
|
||||
}
|
||||
<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
|
||||
@@ -44,7 +69,9 @@
|
||||
[Parameter] public required DateTime Date { get; set; }
|
||||
[Parameter] public EventCallback<DateTime> DateChanged { get; set; }
|
||||
|
||||
private List<CalendarEvent> Events { 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; }
|
||||
@@ -52,17 +79,17 @@
|
||||
|
||||
readonly string[] _giorniSettimana = ["Lu", "Ma", "Me", "Gi", "Ve", "Sa", "Do"];
|
||||
|
||||
protected override void OnInitialized()
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ChangeMonth();
|
||||
await ChangeMonth();
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
ChangeMonth();
|
||||
await ChangeMonth();
|
||||
}
|
||||
|
||||
private void ChangeMonth()
|
||||
private async Task ChangeMonth()
|
||||
{
|
||||
var firstDay = Date;
|
||||
DaysInMonth = DateTime.DaysInMonth(firstDay.Year, firstDay.Month);
|
||||
@@ -74,23 +101,50 @@
|
||||
var totalCell = tempTotalCell * 7;
|
||||
EndDays = totalCell - (DaysInMonth + StartDays);
|
||||
|
||||
Events =
|
||||
[
|
||||
new CalendarEvent { Date = DateTime.Today, Title = "Meeting", Time = "10:00" },
|
||||
new CalendarEvent { Date = DateTime.Today.AddDays(2), Title = "Dentista", Time = "15:30" },
|
||||
new CalendarEvent { Date = DateTime.Today.AddDays(5), Title = "Scadenza", Time = "Tutto il giorno" }
|
||||
];
|
||||
await LoadData();
|
||||
}
|
||||
|
||||
private List<CalendarEvent> GetEventsForDay(DateTime day)
|
||||
private async Task LoadData()
|
||||
{
|
||||
return Events.Where(e => e.Date.Date == day.Date).ToList();
|
||||
// Load = true;
|
||||
// StateHasChanged();
|
||||
|
||||
await Task.Delay(500);
|
||||
var refreshActivity = await RefreshActivity();
|
||||
ActivityList = refreshActivity;
|
||||
// Load = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public class CalendarEvent
|
||||
private async Task<List<ActivityDTO>> RefreshActivity()
|
||||
{
|
||||
public DateTime Date { get; set; }
|
||||
public string Title { get; set; } = "";
|
||||
public string Time { get; set; } = "";
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
.calendar {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
/*border: 1px solid #ccc;*/
|
||||
}
|
||||
|
||||
.calendar-header, .calendar-day {
|
||||
@@ -31,6 +30,11 @@
|
||||
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%;
|
||||
@@ -38,15 +42,28 @@
|
||||
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);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.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 {
|
||||
@@ -61,4 +78,24 @@
|
||||
|
||||
.radiusBottomLeft { border-bottom-left-radius: 12px; }
|
||||
|
||||
.radiusBottomRight { border-bottom-right-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;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
@using ConSegna.Shared.Core.Helpers
|
||||
@using Template.Shared.Core.Dto
|
||||
@using Template.Shared.Core.Dto
|
||||
@using Template.Shared.Core.Interface
|
||||
@using Template.Shared.Components.Layout.Spinner
|
||||
@inject IManageDataService manageData
|
||||
|
||||
<div class="calendar">
|
||||
@@ -8,26 +8,33 @@
|
||||
DateTime? currentDate = null;
|
||||
}
|
||||
|
||||
@if (!Activities.IsNullOrEmpty())
|
||||
@if (Load)
|
||||
{
|
||||
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"/>
|
||||
}
|
||||
<SpinnerLayout FullScreen="false"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<NoDataAvailable Text="Nessuna attività trovata" ImageSource="_content/Template.Shared/images/undraw_file-search_cbur.svg"/>
|
||||
@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>
|
||||
|
||||
@@ -37,6 +44,7 @@
|
||||
[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)
|
||||
{
|
||||
@@ -53,9 +61,13 @@
|
||||
|
||||
private async Task LoadData()
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
Load = true;
|
||||
StateHasChanged();
|
||||
|
||||
await Task.Delay(500);
|
||||
var refreshActivity = await RefreshActivity();
|
||||
Activities = refreshActivity;
|
||||
Load = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
@@ -63,7 +75,7 @@
|
||||
{
|
||||
var activityDto = await Task.Run(async () =>
|
||||
{
|
||||
return Activities = (await manageData.GetActivity(x =>
|
||||
return (await manageData.GetActivity(x =>
|
||||
(x.EffectiveDate == null && x.EstimatedDate >= Date.Start && x.EstimatedDate <= Date.End) ||
|
||||
(x.EffectiveDate >= Date.Start && x.EffectiveDate <= Date.End)
|
||||
))
|
||||
|
||||
@@ -1,31 +1,57 @@
|
||||
@using Template.Shared.Core.Dto
|
||||
@using Template.Shared.Core.Helpers.Enum
|
||||
|
||||
<div class="activity-card @Activity.Category.ConvertToHumanReadable()">
|
||||
<div class="activity-card @Activity.Category.ConvertToHumanReadable()" @onclick="() => OpenActivityForm(Activity.ActivityId)">
|
||||
<div class="activity-left-section">
|
||||
<div class="activity-hours-section">
|
||||
<span class="activity-hours">
|
||||
@if (Activity.EffectiveTime is null)
|
||||
{
|
||||
@($"{Activity.EstimatedTime:t}")
|
||||
}
|
||||
else
|
||||
{
|
||||
@($"{Activity.EffectiveTime:t}")
|
||||
}
|
||||
</span>
|
||||
@if (Durata != null)
|
||||
{
|
||||
<MudChip T="string" Icon="@IconConstants.Chip.Time" Color="Color.Dark" Size="Size.Small">@($"{Durata.Value.TotalHours:####}h")</MudChip>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="activity-body-section">
|
||||
<MudText Class="activity-title" Typo="Typo.button" HtmlTag="h3">@Activity.Commessa</MudText>
|
||||
<MudText Class="activity-subtitle" Typo="Typo.caption">@Activity.ActivityDescription</MudText>
|
||||
<div class="title-section">
|
||||
<MudText Class="activity-title" Typo="Typo.body1" HtmlTag="h3">
|
||||
@switch (Activity.Category)
|
||||
{
|
||||
case ActivityCategoryEnum.Commessa:
|
||||
@Activity.Commessa
|
||||
break;
|
||||
case ActivityCategoryEnum.Interna:
|
||||
@Activity.Cliente
|
||||
break;
|
||||
case ActivityCategoryEnum.Memo:
|
||||
@Activity.ActivityDescription
|
||||
break;
|
||||
default:
|
||||
@("")
|
||||
break;
|
||||
}
|
||||
</MudText>
|
||||
<div class="activity-hours-section">
|
||||
<span class="activity-hours">
|
||||
@if (Activity.EffectiveTime is null)
|
||||
{
|
||||
@($"{Activity.EstimatedTime:t}")
|
||||
}
|
||||
else
|
||||
{
|
||||
@($"{Activity.EffectiveTime:t}")
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@if (Activity.Category != ActivityCategoryEnum.Memo)
|
||||
{
|
||||
<MudText Class="activity-subtitle" Typo="Typo.body1" HtmlTag="p">@Activity.ActivityDescription</MudText>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="activity-info-section">
|
||||
@if (Durata != null && (Durata.Value.TotalHours > 0 || Durata.Value.Minutes > 0))
|
||||
{
|
||||
var ore = (int)Durata.Value.TotalHours;
|
||||
var minuti = Durata.Value.Minutes;
|
||||
|
||||
<MudChip T="string" Icon="@IconConstants.Chip.Time" Color="Color.Dark" Size="Size.Small">
|
||||
@(ore > 0 ? $"{ore}h{(minuti > 0 ? $" {minuti}m" : "")}" : $"{minuti}m")
|
||||
</MudChip>
|
||||
}
|
||||
@if (Activity.ActivityResultId != null)
|
||||
{
|
||||
<MudChip T="string" Icon="@IconConstants.Chip.Stato" Size="Size.Small" Color="Color.Success">@Activity.ActivityResultId</MudChip>
|
||||
@@ -38,7 +64,6 @@
|
||||
[Parameter] public ActivityDTO Activity { get; set; } = new();
|
||||
|
||||
private TimeSpan? Durata { get; set; }
|
||||
private Color ColorStatus { get; set; }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
@@ -46,7 +71,15 @@
|
||||
{
|
||||
{ EffectiveTime: not null, EffectiveEndtime: not null } => Activity.EffectiveEndtime.Value - Activity.EffectiveTime.Value,
|
||||
{ EstimatedTime: not null, EstimatedEndtime: not null } => Activity.EstimatedEndtime.Value - Activity.EstimatedTime.Value,
|
||||
_ => Durata
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
private void OpenActivityForm(string? activityId)
|
||||
{
|
||||
var url = "/activity";
|
||||
url = !activityId.IsNullOrEmpty() ? $"{url}/{activityId}" : url;
|
||||
|
||||
NavigationManager.NavigateTo(url);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
.activity-card {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: .5rem .7rem;
|
||||
flex-direction: column;
|
||||
padding: .5rem .5rem;
|
||||
border-radius: 12px;
|
||||
line-height: normal;
|
||||
border: 1px solid var(--card-border-color);
|
||||
box-shadow: var(--card-shadow);
|
||||
}
|
||||
|
||||
.activity-card.memo { border-left: 5px solid var(--mud-palette-info-darken); }
|
||||
@@ -20,13 +17,14 @@
|
||||
.activity-left-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.activity-hours-section {
|
||||
width: min-content;
|
||||
.title-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.activity-hours { font-weight: 700; }
|
||||
@@ -34,22 +32,24 @@
|
||||
.activity-hours-section ::deep .mud-chip { margin: 5px 0 0 !important; }
|
||||
|
||||
.activity-body-section {
|
||||
width: fit-content;
|
||||
margin: 0 1rem;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.activity-body-section ::deep > .activity-title {
|
||||
.title-section ::deep > .activity-title {
|
||||
font-weight: 800 !important;
|
||||
margin: 0 0 .2rem 0 !important;
|
||||
margin: 0 !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
|
||||
.activity-body-section ::deep > .activity-subtitle {
|
||||
font-size: smaller;
|
||||
color: var(--mud-palette-gray-darker);
|
||||
margin: .2rem 0 !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
|
||||
.activity-info-section { width: min-content; }
|
||||
.activity-info-section {
|
||||
width: min-content;
|
||||
display: flex;
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
.no-data {
|
||||
position: fixed;
|
||||
top: 35%;
|
||||
margin-top: 2rem;
|
||||
width: calc(100vw - (var(--bs-gutter-x) * .5) * 2);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user