feat: Add Terms of Service acceptance checkbox to registration

- Add checkbox requiring users to agree to Terms of Service and Privacy Policy
- Add TermsAcceptedAt field to ApplicationUser to track acceptance
- Link checkbox to actual /terms and /privacy pages
- Remove passive text that was using dead # links

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-25 07:46:16 +00:00
parent 0c42842655
commit 0dc03dd380
15 changed files with 557 additions and 10 deletions

View File

@@ -71,6 +71,17 @@
<ValidationMessage For="() => _model.ConfirmPassword" class="text-danger small mt-1" />
</div>
<div class="mb-4">
<div class="form-check">
<InputCheckbox id="agreeToTerms" class="form-check-input" @bind-Value="_model.AgreeToTerms" />
<label class="form-check-label" for="agreeToTerms">
I agree to the <a href="/terms" target="_blank" class="text-decoration-none">Terms of Service</a>
and have read the <a href="/privacy" target="_blank" class="text-decoration-none">Privacy Policy</a>
</label>
</div>
<ValidationMessage For="() => _model.AgreeToTerms" class="text-danger small mt-1" />
</div>
<div class="d-grid mb-4">
<button type="submit" class="btn btn-primary btn-lg" disabled="@_isLoading">
@if (_isLoading)
@@ -89,13 +100,6 @@
</div>
</EditForm>
<p class="text-center text-muted small mb-4">
By creating an account, you agree to our
<a href="#" class="text-decoration-none">Terms of Service</a>
and
<a href="#" class="text-decoration-none">Privacy Policy</a>
</p>
<div class="auth-divider">
<span>Already have an account?</span>
</div>
@@ -183,7 +187,8 @@
UserName = _model.Email,
Email = _model.Email,
Plan = Domain.Enums.UserPlan.Free,
ChecksUsedThisMonth = 0
ChecksUsedThisMonth = 0,
TermsAcceptedAt = DateTime.UtcNow
};
var result = await UserManager.CreateAsync(user, _model.Password);
@@ -222,5 +227,8 @@
[System.ComponentModel.DataAnnotations.Required(ErrorMessage = "Please confirm your password")]
[System.ComponentModel.DataAnnotations.Compare(nameof(Password), ErrorMessage = "Passwords do not match")]
public string ConfirmPassword { get; set; } = string.Empty;
[System.ComponentModel.DataAnnotations.Range(typeof(bool), "true", "true", ErrorMessage = "You must agree to the Terms of Service")]
public bool AgreeToTerms { get; set; }
}
}