Fix for upcomming lan
This commit is contained in:
parent
204176e40a
commit
c73a54101c
11 changed files with 147 additions and 42 deletions
|
|
@ -24,9 +24,9 @@ services:
|
||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Production
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
# These should be replaced with real values or set in an .env file
|
# These should be replaced with real values or set in an .env file
|
||||||
- EnvironmentVariables__ApiUrl=""
|
- EnvironmentVariables__ApiUrl=${SVEROK_API_URL}
|
||||||
- EnvironmentVariables__ApiKey=""
|
- EnvironmentVariables__ApiKey=${SVEROK_API_KEY}
|
||||||
- EnvironmentVariables__AssociationNumber=""
|
- EnvironmentVariables__AssociationNumber=${SVEROK_ASSOCIATION_NUMBER}
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
|
|
||||||
|
|
@ -43,14 +43,14 @@ services:
|
||||||
- ConnectionStrings__DefaultConnection=Host=postgres;Username=postgres;Password=postgres;Database=postgres;Port=5432
|
- ConnectionStrings__DefaultConnection=Host=postgres;Username=postgres;Password=postgres;Database=postgres;Port=5432
|
||||||
- AuthApi__BaseUrl=http://auth-api:8080
|
- AuthApi__BaseUrl=http://auth-api:8080
|
||||||
- VbytesRelay__BaseUrl=https://api.lan.vbytes.se
|
- VbytesRelay__BaseUrl=https://api.lan.vbytes.se
|
||||||
- VbytesRelay__ApiKey=""
|
- VbytesRelay__ApiKey=${VBYTES_RELAY_API_KEY}
|
||||||
- VbytesRelay__ClientCertificatePfxPath=""
|
- VbytesRelay__ClientCertificatePfxPath=/app/certs/server.pfx
|
||||||
- Security__SsnPepper=""
|
- Security__SsnPepper=${SSN_PEPPER}
|
||||||
- VbytesRelay__VolunteerRegisterPath=/api/volunteer
|
- VbytesRelay__VolunteerRegisterPath=/api/volunteer
|
||||||
- VbytesRelay__ParticipantRegisterPath=/api/participant
|
- VbytesRelay__ParticipantRegisterPath=/api/participant
|
||||||
- Admin__Password=admin
|
- Admin__Password=admin
|
||||||
volumes:
|
volumes:
|
||||||
- ./server.pfx:/app/certs/server.pfx:ro
|
- ./server.pfx:/app/certs/server.pfx:ro,z
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
- auth-api
|
- auth-api
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,26 @@ using Registration.API.RequestModels;
|
||||||
using Registration.API.Services;
|
using Registration.API.Services;
|
||||||
using Registration.API.Validation;
|
using Registration.API.Validation;
|
||||||
using Registration.Domain.Models;
|
using Registration.Domain.Models;
|
||||||
|
using Registration.Infra.Repositories;
|
||||||
|
|
||||||
namespace Registration.API.Controllers;
|
namespace Registration.API.Controllers;
|
||||||
|
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class ParticipantController(IVbytesParticipantRelayService relayService) : ControllerBase
|
public class ParticipantController(IVbytesParticipantRelayService relayService, IRegistrationRepository registrationRepository) : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IVbytesParticipantRelayService _relayService = relayService;
|
private readonly IVbytesParticipantRelayService _relayService = relayService;
|
||||||
|
private readonly IRegistrationRepository _registrationRepository = registrationRepository;
|
||||||
|
|
||||||
[HttpPost("register")]
|
[HttpPost("register")]
|
||||||
public async Task<IActionResult> RegisterForLan([FromBody] ParticipantRegistrationRequest request, CancellationToken cancellationToken)
|
public async Task<IActionResult> RegisterForLan([FromBody] ParticipantRegistrationRequest request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
var content = await _registrationRepository.GetEventContent();
|
||||||
|
if (!content.RegistrationEnabled)
|
||||||
|
{
|
||||||
|
return StatusCode(StatusCodes.Status403Forbidden);
|
||||||
|
}
|
||||||
|
|
||||||
var normalizedGuardianPhone = request.GuardianPhoneNumber.NormalizePhone();
|
var normalizedGuardianPhone = request.GuardianPhoneNumber.NormalizePhone();
|
||||||
var normalizedParticipantPhone = request.PhoneNumber.NormalizeOptionalPhone();
|
var normalizedParticipantPhone = request.PhoneNumber.NormalizeOptionalPhone();
|
||||||
|
|
||||||
|
|
@ -31,7 +39,7 @@ public class ParticipantController(IVbytesParticipantRelayService relayService)
|
||||||
GuardianEmail = request.GuardianEmail.Trim(),
|
GuardianEmail = request.GuardianEmail.Trim(),
|
||||||
IsVisitor = request.IsVisitor!.Value,
|
IsVisitor = request.IsVisitor!.Value,
|
||||||
HasApprovedGdpr = request.HasApprovedGdpr!.Value,
|
HasApprovedGdpr = request.HasApprovedGdpr!.Value,
|
||||||
Friends = request.Friends?.Trim(),
|
Friends = request.IsVisitor == true ? null : request.Friends?.Trim(),
|
||||||
SpecialDiet = request.SpecialDiet?.Trim(),
|
SpecialDiet = request.SpecialDiet?.Trim(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,12 @@ public class RegistrationController(IRegistrationRepository registrationReposito
|
||||||
return errorResult!;
|
return errorResult!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var content = await _registrationRepository.GetEventContent();
|
||||||
|
if (!content.RegistrationEnabled)
|
||||||
|
{
|
||||||
|
return StatusCode(StatusCodes.Status403Forbidden);
|
||||||
|
}
|
||||||
|
|
||||||
var added = await _registrationRepository.AddRegistration(normalizedSsn);
|
var added = await _registrationRepository.AddRegistration(normalizedSsn);
|
||||||
|
|
||||||
return added ? Ok() : Conflict();
|
return added ? Ok() : Conflict();
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,26 @@ using Registration.API.RequestModels;
|
||||||
using Registration.API.Services;
|
using Registration.API.Services;
|
||||||
using Registration.API.Validation;
|
using Registration.API.Validation;
|
||||||
using Registration.Domain.Models;
|
using Registration.Domain.Models;
|
||||||
|
using Registration.Infra.Repositories;
|
||||||
|
|
||||||
namespace Registration.API.Controllers;
|
namespace Registration.API.Controllers;
|
||||||
|
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class VolunteerController(IVbytesVolunteerRelayService relayService) : ControllerBase
|
public class VolunteerController(IVbytesVolunteerRelayService relayService, IRegistrationRepository registrationRepository) : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IVbytesVolunteerRelayService _relayService = relayService;
|
private readonly IVbytesVolunteerRelayService _relayService = relayService;
|
||||||
|
private readonly IRegistrationRepository _registrationRepository = registrationRepository;
|
||||||
|
|
||||||
[HttpPost("register")]
|
[HttpPost("register")]
|
||||||
public async Task<IActionResult> RegisterVolunteer([FromBody] VolunteerRegistrationRequest request, CancellationToken cancellationToken)
|
public async Task<IActionResult> RegisterVolunteer([FromBody] VolunteerRegistrationRequest request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
var content = await _registrationRepository.GetEventContent();
|
||||||
|
if (!content.VolunteerRegistrationEnabled)
|
||||||
|
{
|
||||||
|
return StatusCode(StatusCodes.Status403Forbidden);
|
||||||
|
}
|
||||||
|
|
||||||
var normalizedPhone = request.PhoneNumber.NormalizePhone();
|
var normalizedPhone = request.PhoneNumber.NormalizePhone();
|
||||||
|
|
||||||
var trimmedAreas = request.AreasOfInterest
|
var trimmedAreas = request.AreasOfInterest
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ public record ParticipantRelayDto(
|
||||||
[property: JsonPropertyName("member")] bool Member,
|
[property: JsonPropertyName("member")] bool Member,
|
||||||
[property: JsonPropertyName("first_name")] string FirstName,
|
[property: JsonPropertyName("first_name")] string FirstName,
|
||||||
[property: JsonPropertyName("surname")] string Surname,
|
[property: JsonPropertyName("surname")] string Surname,
|
||||||
|
[property: JsonPropertyName("ssn")] string? Ssn,
|
||||||
[property: JsonPropertyName("grade")] string Grade,
|
[property: JsonPropertyName("grade")] string Grade,
|
||||||
[property: JsonPropertyName("phone")] string? Phone,
|
[property: JsonPropertyName("phone")] string? Phone,
|
||||||
[property: JsonPropertyName("email")] string? Email,
|
[property: JsonPropertyName("email")] string? Email,
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ public class ParticipantRegistrationRequest
|
||||||
public string SurName { get; set; } = string.Empty;
|
public string SurName { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
[RegularExpression(@"^([1-9]|Gymnasium [1-3])$",
|
[RegularExpression(@"^([1-9]|1[1-3])$",
|
||||||
ErrorMessage = "Årkurs måste vara 1–9 eller Gymnasium 1–3.")]
|
ErrorMessage = "Årkurs måste vara 1–9 eller 11–13.")]
|
||||||
public string Grade { get; set; } = string.Empty;
|
public string Grade { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string? PhoneNumber { get; set; }
|
public string? PhoneNumber { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ public class VbytesParticipantRelayService(
|
||||||
Member: participant.IsMember,
|
Member: participant.IsMember,
|
||||||
FirstName: participant.FirstName,
|
FirstName: participant.FirstName,
|
||||||
Surname: participant.SurName,
|
Surname: participant.SurName,
|
||||||
|
Ssn: null,
|
||||||
Grade: participant.Grade,
|
Grade: participant.Grade,
|
||||||
Phone: participant.PhoneNumber,
|
Phone: participant.PhoneNumber,
|
||||||
Email: participant.Email,
|
Email: participant.Email,
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,20 @@ using Registration.API.Controllers;
|
||||||
using Registration.API.RequestModels;
|
using Registration.API.RequestModels;
|
||||||
using Registration.API.Services;
|
using Registration.API.Services;
|
||||||
using Registration.Domain.Models;
|
using Registration.Domain.Models;
|
||||||
|
using Registration.Infra.Repositories;
|
||||||
|
|
||||||
namespace Registration.Tests.Controllers;
|
namespace Registration.Tests.Controllers;
|
||||||
|
|
||||||
public class ParticipantControllerTests
|
public class ParticipantControllerTests
|
||||||
{
|
{
|
||||||
private readonly Mock<IVbytesParticipantRelayService> _relay = new();
|
private readonly Mock<IVbytesParticipantRelayService> _relay = new();
|
||||||
|
private readonly Mock<IRegistrationRepository> _repo = new();
|
||||||
|
|
||||||
private ParticipantController Sut() => new(_relay.Object);
|
private ParticipantController Sut(EventContent? content = null)
|
||||||
|
{
|
||||||
|
_repo.Setup(r => r.GetEventContent()).ReturnsAsync(content ?? new EventContent());
|
||||||
|
return new(_relay.Object, _repo.Object);
|
||||||
|
}
|
||||||
|
|
||||||
private static ParticipantRegistrationRequest ValidRequest() => new()
|
private static ParticipantRegistrationRequest ValidRequest() => new()
|
||||||
{
|
{
|
||||||
|
|
@ -73,6 +79,33 @@ public class ParticipantControllerTests
|
||||||
Assert.Null(captured!.PhoneNumber);
|
Assert.Null(captured!.PhoneNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RegisterForLan_returns_Forbidden_when_registration_disabled()
|
||||||
|
{
|
||||||
|
var result = await Sut(new EventContent { RegistrationEnabled = false })
|
||||||
|
.RegisterForLan(ValidRequest(), CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.IsType<StatusCodeResult>(result);
|
||||||
|
Assert.Equal(403, ((StatusCodeResult)result).StatusCode);
|
||||||
|
_relay.Verify(r => r.RegisterParticipantAsync(It.IsAny<Participant>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RegisterForLan_clears_friends_for_visitors()
|
||||||
|
{
|
||||||
|
Participant? captured = null;
|
||||||
|
_relay.Setup(r => r.RegisterParticipantAsync(It.IsAny<Participant>(), It.IsAny<CancellationToken>()))
|
||||||
|
.Callback<Participant, CancellationToken>((p, _) => captured = p)
|
||||||
|
.ReturnsAsync(new VbytesRelayResult(true, 200, "ok"));
|
||||||
|
|
||||||
|
var req = ValidRequest();
|
||||||
|
req.IsVisitor = true;
|
||||||
|
|
||||||
|
await Sut().RegisterForLan(req, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.Null(captured!.Friends);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task RegisterForLan_returns_Unauthorized_when_relay_fails()
|
public async Task RegisterForLan_returns_Unauthorized_when_relay_fails()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Registration.API.Controllers;
|
using Registration.API.Controllers;
|
||||||
using Registration.API.Services;
|
using Registration.API.Services;
|
||||||
|
using Registration.Domain.Models;
|
||||||
using Registration.Infra.Repositories;
|
using Registration.Infra.Repositories;
|
||||||
|
|
||||||
namespace Registration.Tests.Controllers;
|
namespace Registration.Tests.Controllers;
|
||||||
|
|
@ -11,7 +12,11 @@ public class RegistrationControllerTests
|
||||||
private readonly Mock<IRegistrationRepository> _repo = new();
|
private readonly Mock<IRegistrationRepository> _repo = new();
|
||||||
private readonly Mock<IAuthService> _auth = new();
|
private readonly Mock<IAuthService> _auth = new();
|
||||||
|
|
||||||
private RegistrationController Sut() => new(_repo.Object, _auth.Object);
|
private RegistrationController Sut(EventContent? content = null)
|
||||||
|
{
|
||||||
|
_repo.Setup(r => r.GetEventContent()).ReturnsAsync(content ?? new EventContent());
|
||||||
|
return new(_repo.Object, _auth.Object);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ValidateSsn_returns_400_for_invalid_ssn()
|
public async Task ValidateSsn_returns_400_for_invalid_ssn()
|
||||||
|
|
@ -74,6 +79,17 @@ public class RegistrationControllerTests
|
||||||
Assert.IsType<ConflictResult>(result);
|
Assert.IsType<ConflictResult>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RegisterMember_returns_Forbidden_when_registration_disabled()
|
||||||
|
{
|
||||||
|
var result = await Sut(new EventContent { RegistrationEnabled = false })
|
||||||
|
.RegisterMember("19900101-1234", CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.IsType<StatusCodeResult>(result);
|
||||||
|
Assert.Equal(403, ((StatusCodeResult)result).StatusCode);
|
||||||
|
_repo.Verify(r => r.AddRegistration(It.IsAny<string>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task IsMemberRegistered_returns_400_for_invalid_ssn()
|
public async Task IsMemberRegistered_returns_400_for_invalid_ssn()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,20 @@ using Registration.API.Controllers;
|
||||||
using Registration.API.RequestModels;
|
using Registration.API.RequestModels;
|
||||||
using Registration.API.Services;
|
using Registration.API.Services;
|
||||||
using Registration.Domain.Models;
|
using Registration.Domain.Models;
|
||||||
|
using Registration.Infra.Repositories;
|
||||||
|
|
||||||
namespace Registration.Tests.Controllers;
|
namespace Registration.Tests.Controllers;
|
||||||
|
|
||||||
public class VolunteerControllerTests
|
public class VolunteerControllerTests
|
||||||
{
|
{
|
||||||
private readonly Mock<IVbytesVolunteerRelayService> _relay = new();
|
private readonly Mock<IVbytesVolunteerRelayService> _relay = new();
|
||||||
|
private readonly Mock<IRegistrationRepository> _repo = new();
|
||||||
|
|
||||||
private VolunteerController Sut() => new(_relay.Object);
|
private VolunteerController Sut(EventContent? content = null)
|
||||||
|
{
|
||||||
|
_repo.Setup(r => r.GetEventContent()).ReturnsAsync(content ?? new EventContent());
|
||||||
|
return new(_relay.Object, _repo.Object);
|
||||||
|
}
|
||||||
|
|
||||||
private static VolunteerRegistrationRequest ValidRequest() => new()
|
private static VolunteerRegistrationRequest ValidRequest() => new()
|
||||||
{
|
{
|
||||||
|
|
@ -72,6 +78,17 @@ public class VolunteerControllerTests
|
||||||
_relay.Verify(r => r.RegisterVolunteerAsync(It.IsAny<Volunteer>(), It.IsAny<CancellationToken>()), Times.Never);
|
_relay.Verify(r => r.RegisterVolunteerAsync(It.IsAny<Volunteer>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RegisterVolunteer_returns_Forbidden_when_volunteer_registration_disabled()
|
||||||
|
{
|
||||||
|
var result = await Sut(new EventContent { VolunteerRegistrationEnabled = false })
|
||||||
|
.RegisterVolunteer(ValidRequest(), CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.IsType<StatusCodeResult>(result);
|
||||||
|
Assert.Equal(403, ((StatusCodeResult)result).StatusCode);
|
||||||
|
_relay.Verify(r => r.RegisterVolunteerAsync(It.IsAny<Volunteer>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task RegisterVolunteer_returns_Unauthorized_when_relay_fails()
|
public async Task RegisterVolunteer_returns_Unauthorized_when_relay_fails()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,7 @@ export default function RegisterPage() {
|
||||||
`${trimmedGuardianFirstName} ${trimmedGuardianLastName}`.trim(),
|
`${trimmedGuardianFirstName} ${trimmedGuardianLastName}`.trim(),
|
||||||
guardianPhoneNumber: normalizedGuardianPhone,
|
guardianPhoneNumber: normalizedGuardianPhone,
|
||||||
guardianEmail: trimmedGuardianEmail,
|
guardianEmail: trimmedGuardianEmail,
|
||||||
friends: formData.friends.trim(),
|
friends: formData.isVisitor ? "" : formData.friends.trim(),
|
||||||
specialDiet: formData.specialDiet.trim(),
|
specialDiet: formData.specialDiet.trim(),
|
||||||
isMember: isMember,
|
isMember: isMember,
|
||||||
};
|
};
|
||||||
|
|
@ -258,19 +258,28 @@ export default function RegisterPage() {
|
||||||
setMessage({
|
setMessage({
|
||||||
type: "success",
|
type: "success",
|
||||||
text: isMember
|
text: isMember
|
||||||
? "Registreringen är klar! Du är nu anmäld till LAN:et."
|
? "Registreringen är klar! Du är nu anmäld till LAN:et. En bekräftelse skickas via e-post/SMS till vårdnadshavaren."
|
||||||
: "Din anmälan är mottagen, men det återstår ett viktigt steg för att du ska få delta.",
|
: "Din anmälan är mottagen, men det återstår ett viktigt steg för att du ska få delta. En bekräftelse skickas via e-post/SMS till vårdnadshavaren när anmälan är godkänd.",
|
||||||
});
|
});
|
||||||
setShowBecomeMemberCta(!isMember);
|
setShowBecomeMemberCta(!isMember);
|
||||||
|
|
||||||
await fetch(`/api/Registration/register/${normalizedSsn}`, {
|
await fetch(`/api/Registration/register/${normalizedSsn}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
});
|
});
|
||||||
|
} else if (response.status === 403) {
|
||||||
|
setContent((prev) => (prev ? { ...prev, registrationEnabled: false } : prev));
|
||||||
|
setMessage({ type: "", text: "" });
|
||||||
} else {
|
} else {
|
||||||
const errorData = await response.json();
|
let text = "Registreringen misslyckades.";
|
||||||
|
try {
|
||||||
|
const errorData = await response.json();
|
||||||
|
text = errorData.message || text;
|
||||||
|
} catch {
|
||||||
|
// response without JSON body
|
||||||
|
}
|
||||||
setMessage({
|
setMessage({
|
||||||
type: "error",
|
type: "error",
|
||||||
text: errorData.message || "Registreringen misslyckades.",
|
text,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -452,11 +461,11 @@ export default function RegisterPage() {
|
||||||
))}
|
))}
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="Gymnasium">
|
<optgroup label="Gymnasium">
|
||||||
{["1", "2", "3"].map((g) => (
|
{["11", "12", "13"].map((g) => (
|
||||||
<option key={`gym${g}`} value={`Gymnasium ${g}`}>
|
<option key={`gym${g}`} value={g}>
|
||||||
Gymnasium {g}
|
Gymnasiet {g}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</optgroup>
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
{fieldErrors.grade && (
|
{fieldErrors.grade && (
|
||||||
|
|
@ -509,9 +518,13 @@ export default function RegisterPage() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="sm:col-span-2 pt-4 border-t border-gray-100 mt-4">
|
<div className="sm:col-span-2 pt-4 border-t border-gray-100 mt-4">
|
||||||
<h3 className="text-lg font-medium text-gray-900 mb-4">
|
<h3 className="text-lg font-medium text-gray-900 mb-1">
|
||||||
Vårdnadshavares Information
|
Vårdnadshavares Information
|
||||||
</h3>
|
</h3>
|
||||||
|
<p className="text-xs text-gray-500 mb-4">
|
||||||
|
Bekräftelse via e-post och SMS skickas endast hit till
|
||||||
|
vårdnadshavaren – inte till den anmäldes uppgifter ovan.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -616,22 +629,24 @@ export default function RegisterPage() {
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="sm:col-span-2">
|
{!formData.isVisitor && (
|
||||||
<label
|
<div className="sm:col-span-2">
|
||||||
htmlFor="friends"
|
<label
|
||||||
className="block text-sm font-medium text-gray-700"
|
htmlFor="friends"
|
||||||
>
|
className="block text-sm font-medium text-gray-700"
|
||||||
"Önska" Vänner (att sitta jämte)
|
>
|
||||||
</label>
|
"Önska" Vänner (att sitta jämte)
|
||||||
<input
|
</label>
|
||||||
type="text"
|
<input
|
||||||
name="friends"
|
type="text"
|
||||||
id="friends"
|
name="friends"
|
||||||
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm p-2 border text-gray-900"
|
id="friends"
|
||||||
value={formData.friends}
|
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm p-2 border text-gray-900"
|
||||||
onChange={handleInputChange}
|
value={formData.friends}
|
||||||
/>
|
onChange={handleInputChange}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="sm:col-span-2">
|
<div className="sm:col-span-2">
|
||||||
<label
|
<label
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue