b59ad6e5ab
Build and Push Docker Image / build-and-push (push) Successful in 27s
Introduced centralized RESX localization with hierarchical keys for multi-language support. Added resource files for English, French, Dutch (Belgium), and pseudo-localization. Replaced hardcoded strings in Razor components with localized string references. Added a `PreferredCulture` property to `ApplicationUser` with a migration to store user-specific culture preferences. Implemented `LocalizationService` to manage supported cultures and user preferences. Added a language picker in `TopBar.razor` and configured `RequestLocalizationOptions` for culture detection. Localized registry-related components and error messages. Enhanced UI elements to dynamically display localized content. Added pseudo-localization to identify hardcoded strings during development.
175 lines
7.7 KiB
Plaintext
175 lines
7.7 KiB
Plaintext
@page "/"
|
|
|
|
@using BirthList.Web.Features.Registries
|
|
|
|
<PageTitle>@L["Home.PageTitle"]</PageTitle>
|
|
|
|
<h1>@L["Home.Welcome"]</h1>
|
|
|
|
<AuthorizeView>
|
|
<Authorized Context="authState">
|
|
<div class="registry-sections">
|
|
<div class="mb-4">
|
|
<div class="section-header">
|
|
<h2>@L["Home.ManagedRegistries"]</h2>
|
|
<button class="btn btn-primary btn-sm" @onclick="() => ShowCreateForm = !ShowCreateForm">
|
|
<span class="bi bi-plus"></span> @L["Home.CreateNew"]
|
|
</button>
|
|
</div>
|
|
@if (MyRegistries.Count == 0)
|
|
{
|
|
<p class="text-muted">@L["Home.NoRegistries"]</p>
|
|
}
|
|
else
|
|
{
|
|
<div class="registry-grid">
|
|
@foreach (var registry in MyRegistries)
|
|
{
|
|
<div class="registry-card">
|
|
<h3>@registry.Title</h3>
|
|
<div class="registry-actions">
|
|
<a href="/registry/@registry.PublicLinkCode" class="btn btn-outline-primary btn-sm">@L["Home.View"]</a>
|
|
<a href="/registry/@registry.Id/admin" class="btn btn-outline-secondary btn-sm">@L["Home.Manage"]</a>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<h2>@L["Home.VisitedRegistries"]</h2>
|
|
@if (VisitedRegistries.Count == 0)
|
|
{
|
|
<p class="text-muted">@L["Home.NoVisitedRegistries"]</p>
|
|
}
|
|
else
|
|
{
|
|
<div class="registry-grid">
|
|
@foreach (var registry in VisitedRegistries)
|
|
{
|
|
<div class="registry-card">
|
|
<h3>@registry.Title</h3>
|
|
<div class="registry-actions">
|
|
<a href="/registry/@registry.PublicLinkCode" class="btn btn-outline-primary btn-sm">@L["Home.View"]</a>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
@if (ShowCreateForm)
|
|
{
|
|
<div class="create-registry-modal-overlay" @onclick="() => ShowCreateForm = false">
|
|
<div class="create-registry-modal" @onclick:stopPropagation="true">
|
|
<div class="modal-header">
|
|
<h3 class="modal-title">@L["Home.CreateRegistryTitle"]</h3>
|
|
<button type="button" class="btn-close" @onclick="() => ShowCreateForm = false"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<EditForm Model="Model" OnValidSubmit="CreateRegistryAsync" Context="formContext" FormName="create-registry-form">
|
|
<DataAnnotationsValidator />
|
|
<div class="mb-3">
|
|
<label class="form-label">@L["Home.Title"]</label>
|
|
<InputText class="form-control" @bind-Value="Model.Title" />
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">@L["Home.Type"]</label>
|
|
<InputSelect class="form-select" @bind-Value="Model.RegistryType">
|
|
<option value="@BirthList.Domain.Entities.RegistryType.Birth">@L["Home.RegistryType.Birth"]</option>
|
|
<option value="@BirthList.Domain.Entities.RegistryType.Wedding">@L["Home.RegistryType.Wedding"]</option>
|
|
<option value="@BirthList.Domain.Entities.RegistryType.Birthday">@L["Home.RegistryType.Birthday"]</option>
|
|
</InputSelect>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">@L["Home.Theme"]</label>
|
|
<InputSelect class="form-select" @bind-Value="Model.ThemeKey">
|
|
<option value="default">@L["Home.Theme.Default"]</option>
|
|
<option value="soft">@L["Home.Theme.Soft"]</option>
|
|
<option value="modern">@L["Home.Theme.Modern"]</option>
|
|
</InputSelect>
|
|
</div>
|
|
@if (!string.IsNullOrWhiteSpace(ErrorMessage))
|
|
{
|
|
<div class="alert alert-danger mb-3">@ErrorMessage</div>
|
|
}
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-outline-secondary" @onclick="() => ShowCreateForm = false">@L["Common.Cancel"]</button>
|
|
<button class="btn btn-primary" type="submit">@L["Home.CreateNew"]</button>
|
|
</div>
|
|
</EditForm>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
</Authorized>
|
|
<NotAuthorized>
|
|
<div class="alert alert-info mt-4">
|
|
<p>
|
|
@L["Home.LoginPromptPrefix"]<a href="Account/Login">@L["Home.LoginPromptLinkText"]</a>@L["Home.LoginPromptSuffix"]
|
|
</p>
|
|
</div>
|
|
</NotAuthorized>
|
|
</AuthorizeView>
|
|
|
|
@code {
|
|
[SupplyParameterFromForm(FormName = "create-registry-form")]
|
|
protected RegistryCreateModel Model { get; set; } = new();
|
|
|
|
protected IReadOnlyList<RegistrySummaryViewModel> MyRegistries { get; private set; } = [];
|
|
protected IReadOnlyList<RegistrySummaryViewModel> VisitedRegistries { get; private set; } = [];
|
|
protected string? ErrorMessage { get; private set; }
|
|
protected bool ShowCreateForm { get; private set; }
|
|
|
|
[Inject] private RegistryService RegistryService { get; set; } = null!;
|
|
[Inject] private RegistryUserContext RegistryUserContext { get; set; } = null!;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
await LoadAsync().ConfigureAwait(false);
|
|
}
|
|
|
|
protected async Task CreateRegistryAsync()
|
|
{
|
|
ErrorMessage = null;
|
|
|
|
var userId = await RegistryUserContext.GetUserIdAsync(CancellationToken.None).ConfigureAwait(false);
|
|
if (string.IsNullOrWhiteSpace(userId))
|
|
{
|
|
ErrorMessage = L["Home.MustBeLoggedIn"];
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(Model.Title))
|
|
{
|
|
ErrorMessage = L["Home.TitleRequired"];
|
|
return;
|
|
}
|
|
|
|
await RegistryService.CreateRegistryAsync(userId, Model, CancellationToken.None).ConfigureAwait(false);
|
|
Model = new RegistryCreateModel
|
|
{
|
|
RegistryType = Model.RegistryType,
|
|
ThemeKey = Model.ThemeKey
|
|
};
|
|
ShowCreateForm = false;
|
|
await LoadAsync().ConfigureAwait(false);
|
|
}
|
|
|
|
private async Task LoadAsync()
|
|
{
|
|
var userId = await RegistryUserContext.GetUserIdAsync(CancellationToken.None).ConfigureAwait(false);
|
|
if (string.IsNullOrWhiteSpace(userId))
|
|
{
|
|
MyRegistries = [];
|
|
VisitedRegistries = [];
|
|
return;
|
|
}
|
|
|
|
MyRegistries = await RegistryService.GetAdminRegistriesAsync(userId, CancellationToken.None).ConfigureAwait(false);
|
|
VisitedRegistries = await RegistryService.GetVisitedRegistriesAsync(userId, CancellationToken.None).ConfigureAwait(false);
|
|
}
|
|
}
|