Files
decePubClient/Pages/Join.razor
T

123 lines
5.1 KiB
Plaintext
Raw Normal View History

@page "/join"
@inherits LocalizableComponentBase
<Title>@Localizer["Join with an invitation"]</Title>
@* A new login through a group's invitation (PrivaPub's /clientapi/user/invitation/signup): sign-up is otherwise closed,
so this is how everyone but the first administrator arrives. Its first persona joins the group. A group's page links
here with the code (?code=). *@
<section class="block relative w-full h-full neo-inset neo-xs rounded-xl">
<div class="flex flex-col items-center gap-6 p-4 md:p-5 w-full h-full absolute overflow-y-auto">
@if (CascadingState.IsSignedIn)
{
<div class="flex flex-col gap-3 w-full max-w-sm mt-6 md:mt-16 p-5 rounded-xl neo-raised neo-sm" data-join-signed-in>
<h1 class="text-xl font-bold">@Localizer["You are signed in"]</h1>
<p class="text-sm">@Localizer["A persona of yours joins a group by its invitation in Groups."]</p>
<DButton Href="groups" Color="DColor.Primary">@Localizer["Groups"]</DButton>
</div>
}
else
{
<EditForm Model="form" OnValidSubmit="SignUp" class="flex flex-col gap-4 w-full max-w-sm mt-6 md:mt-16 p-5 rounded-xl neo-raised neo-sm" data-join>
<DataAnnotationsValidator />
<h1 class="text-xl font-bold">@Localizer["Join with an invitation"]</h1>
<p class="text-sm opacity-70">@Localizer["A group's invitation makes your login here, and your first persona joins the group."]</p>
<label class="flex flex-col gap-1">
<span class="text-sm">@Localizer["Invitation code"]</span>
<DInput TValue="string" class="w-full font-mono text-xs" @bind-Value="form.InvitationCode" autocomplete="off" autocapitalize="none" spellcheck="false"
maxlength="@PrivaPub.ClientModels.Constants.GroupInvitationLength" data-join-code />
</label>
<DInput TValue="string" Type="password" class="w-full" @bind-Value="form.InvitationPassword" autocomplete="off"
placeholder="@Localizer["Invitation password, if it has one"]" data-join-code-password />
<b class="text-sm">@Localizer["Your login"]</b>
<label class="flex flex-col gap-1">
<span class="text-sm">@Localizer["Username"]</span>
<DInput TValue="string" class="w-full" @bind-Value="form.UserName" autocomplete="username" autocapitalize="none" spellcheck="false" data-join-username>
<Prefix><i class="ion-md-person"></i></Prefix>
</DInput>
</label>
<label class="flex flex-col gap-1">
<span class="text-sm">@Localizer["Password"]</span>
<DInput TValue="string" Type="password" class="w-full" @bind-Value="form.Password" autocomplete="new-password" data-join-password>
<Prefix><i class="ion-md-key"></i></Prefix>
</DInput>
</label>
<label class="flex flex-col gap-1">
<span class="text-sm">@Localizer["Repeat the password"]</span>
<DInput TValue="string" Type="password" class="w-full" @bind-Value="repeatedPassword" autocomplete="new-password" data-join-repeat>
<Prefix><i class="ion-md-key"></i></Prefix>
</DInput>
</label>
<b class="text-sm">@Localizer["Your first persona"]</b>
<p class="text-xs opacity-70">@Localizer["Others see your personas, never your login."]</p>
<DInput TValue="string" class="w-full" @bind-Value="form.AvatarUserName" autocomplete="off" autocapitalize="none" spellcheck="false"
maxlength="@PrivaPub.ClientModels.Constants.MaxAvatarNameLength" placeholder="@Localizer["user name (a-z, 0-9, _)"]" data-join-persona-username>
<Prefix>@@</Prefix>
</DInput>
<DInput TValue="string" class="w-full" @bind-Value="form.AvatarName" autocomplete="off" maxlength="64"
placeholder="@Localizer["Display name"]" data-join-persona-name />
<ErrorViewer AdditionalError="@error" />
<DButton Type="submit" Color="DColor.Primary" Disabled="IsDefaultDisabled || isWorking" data-join-submit>
@if (isWorking)
{
<DLoading Size="DSize.Sm" LabelText="@Localizer["loading"]" />
}
<span>@Localizer["Join"]</span>
</DButton>
<a class="link text-sm self-center touch-target" href="login">@Localizer["I have a login: sign in"]</a>
</EditForm>
}
</div>
</section>
@code {
[Inject] AuthService AuthService { get; set; }
readonly InvitationLoginForm form = new();
string repeatedPassword;
string error;
bool isWorking;
[SupplyParameterFromQuery] public string Code { get; set; }
protected override void OnInitialized()
{
form.InvitationCode = Code?.Trim();
IsLoading = false;
}
async Task SignUp()
{
error = default;
if (form.Password != repeatedPassword)
{
error = Localizer["The two passwords don't match."];
return;
}
isWorking = true;
form.InvitationCode = form.InvitationCode?.Trim();
form.InvitationPassword = string.IsNullOrEmpty(form.InvitationPassword) ? null : form.InvitationPassword;
form.AvatarUserName = form.AvatarUserName?.Trim().TrimStart('@').ToLowerInvariant();
var result = await AuthService.Join(form);
if (result.IsInvalid)
{
isWorking = false;
error = result.ErrorMessage;
return;
}
await CascadingState.LoadSession();
isWorking = false;
Toast.AddResponseSuccess(Localizer["Welcome: your persona is in the group."]);
Navigation.NavigateTo("");
}
}