Skip to content

Instantly share code, notes, and snippets.

@Pismice
Created July 20, 2025 22:15
Show Gist options
  • Save Pismice/2351d6825043d0c50fb101538151b6f5 to your computer and use it in GitHub Desktop.
Save Pismice/2351d6825043d0c50fb101538151b6f5 to your computer and use it in GitHub Desktop.
<script lang="ts">
import { enhance } from '$app/forms';
import { goto } from '$app/navigation';
import { profilePictureTimestamp, refreshProfilePicture } from '$lib/stores/profilePicture.js';
import * as m from '$lib/paraglide/messages';
import { ConsoleLogWriter } from 'drizzle-orm';
import { flushSync } from 'svelte';
type UserWithProfilePicture = {
firstname: string;
lastname: string;
id: string;
username: string;
email: string;
telephone?: string | null;
hasProfilePicture: boolean;
emailVerified: boolean;
phoneVerified: boolean;
};
let { data }: { data: { user: UserWithProfilePicture } } = $props();
let selectedFile = $state<File | null>(null);
let lol = $state('lol');
let displayLol = $derived(lol);
let isResendingEmail = $state(false);
let emailMessage = $state<string | null>(null);
let emailMessageType = $state<'success' | 'error' | null>(null);
// Phone verification states
let phoneNumber = $state('');
let countryCode = $state('+33');
let fullPhoneNumber = $state(data.user.telephone || '');
let showConfirmationModal = $state(false);
let script: HTMLScriptElement;
let captchaToken = $state('');
// Modal states for complete verification flow
let modalStep = $state<
'confirm' | 'sending' | 'code_sent' | 'enter_code' | 'verifying' | 'success' | 'error'
>('confirm');
let modalMessage = $state('');
let modalMessageType = $state<'success' | 'error' | null>(null);
let tempPhoneNumber = $state('');
let verificationCode = $state('');
// Country codes with flags
const countryCodes = [
{ code: '+33', country: 'FR', flag: '🇫🇷', name: m.france() },
{ code: '+39', country: 'IT', flag: '🇮🇹', name: m.italy() },
{ code: '+41', country: 'CH', flag: '🇨🇭', name: m.switzerland() },
{ code: '+43', country: 'AT', flag: '🇦🇹', name: m.austria() },
{ code: '+49', country: 'DE', flag: '🇩🇪', name: m.germany() }
];
const sortedCountryCodes = countryCodes.sort((a, b) => a.name.localeCompare(b.name));
// TODO delete
$effect(() => {
console.log('lol changed in effect:', lol);
const h2 = document.querySelector('h4');
if (h2) h2.textContent = lol;
});
// Update fullPhoneNumber when country code or phone number changes
$effect(() => {
// Remove leading zero from phone number before combining with country code
const cleanPhoneNumber = phoneNumber.replace(/^0/, '');
fullPhoneNumber = countryCode + cleanPhoneNumber.replace(/\s/g, ''); // Also remove spaces
});
// Parse existing telephone number if user has one
$effect(() => {
if (data.user.telephone) {
const existingPhone = data.user.telephone;
const matchingCountry = countryCodes.find((c) => existingPhone.startsWith(c.code));
if (matchingCountry) {
countryCode = matchingCountry.code;
let localNumber = existingPhone.substring(matchingCountry.code.length);
// Add leading zero for display if the country code is Swiss (+41) and number doesn't start with 0
if (matchingCountry.code === '+41' && !localNumber.startsWith('0')) {
localNumber = '0' + localNumber;
}
// Format the phone number with spaces for display
phoneNumber = formatPhoneNumber(localNumber);
} else {
// Fallback if no matching country code found
countryCode = '+33';
const fallbackNumber = existingPhone.replace(/^\+\d+/, '');
phoneNumber = formatPhoneNumber(fallbackNumber);
}
}
});
// Format phone number with spaces (Swiss style: "079 548 17 17")
function formatPhoneNumber(value: string): string {
// Remove all non-digits
const digits = value.replace(/\D/g, '');
// Apply Swiss formatting: XXX XXX XX XX
if (digits.length <= 3) {
return digits;
} else if (digits.length <= 6) {
return `${digits.slice(0, 3)} ${digits.slice(3)}`;
} else if (digits.length <= 8) {
return `${digits.slice(0, 3)} ${digits.slice(3, 6)} ${digits.slice(6)}`;
} else {
return `${digits.slice(0, 3)} ${digits.slice(3, 6)} ${digits.slice(6, 8)} ${digits.slice(8, 10)}`;
}
}
// Handle phone number input formatting
function handlePhoneInput(event: Event) {
const target = event.target as HTMLInputElement;
const cursorPosition = target.selectionStart || 0;
const oldValue = target.value;
const newValue = formatPhoneNumber(target.value);
// Update the bound value
phoneNumber = newValue;
// Calculate new cursor position
const digitsBefore = oldValue.slice(0, cursorPosition).replace(/\D/g, '').length;
let newCursorPosition = 0;
let digitCount = 0;
for (let i = 0; i < newValue.length && digitCount < digitsBefore; i++) {
if (/\d/.test(newValue[i])) {
digitCount++;
}
newCursorPosition = i + 1;
}
// Set cursor position after the DOM updates
setTimeout(() => {
target.setSelectionRange(newCursorPosition, newCursorPosition);
}, 0);
}
function handleFileChange(event: Event) {
console.log(selectedFile?.name);
const target = event.target as HTMLInputElement;
selectedFile = target.files?.[0] || null;
lol = 'c plus des lol';
console.log(selectedFile?.name);
}
// Handle send verification code with confirmation
function handleSendVerificationCodeUI() {
script = document.createElement('script');
script.src = 'https://www.google.com/recaptcha/api.js';
script.async = true;
script.defer = true;
document.head.appendChild(script);
script.onerror = () => {
console.error('Failed to load reCAPTCHA script');
};
// Make reCAPTCHA callback globally available
(window as any).onRecaptchaValidated = (token: string) => {
captchaToken = token;
};
tempPhoneNumber = fullPhoneNumber;
modalStep = 'confirm';
modalMessage = '';
verificationCode = '';
captchaToken = ''; // Reset captcha token
showConfirmationModal = true;
}
// Confirm and send verification code
async function confirmAndSendCode() {
if (!captchaToken) {
alert('Please complete the CAPTCHA');
return;
}
modalStep = 'sending';
modalMessage = 'Envoi du SMS en cours...';
try {
const formData = new FormData();
formData.append('phoneNumber', tempPhoneNumber);
formData.append('captchaToken', captchaToken); // Add captcha token to form data
const response = await fetch('?/updateAndSendVerification', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.type === 'success') {
modalStep = 'enter_code';
modalMessage = result.data?.message || 'Code envoyé avec succès !';
// Update the user's phone number in the UI
data.user.telephone = tempPhoneNumber;
data.user.phoneVerified = false;
} else {
modalStep = 'error';
modalMessage = result.data?.message || "Erreur lors de l'envoi du SMS";
}
} catch (error) {
modalStep = 'error';
modalMessage = 'Erreur de connexion. Veuillez réessayer.';
}
}
// Verify the entered code
async function verifyCode() {
if (!verificationCode || verificationCode.length !== 6) {
modalMessage = 'Veuillez saisir un code à 6 chiffres';
modalMessageType = 'error';
return;
}
modalStep = 'verifying';
modalMessage = 'Vérification du code...';
modalMessageType = null;
try {
const formData = new FormData();
formData.append('verificationCode', verificationCode);
const response = await fetch('?/verifyPhoneCode', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.type === 'success') {
modalStep = 'success';
modalMessage = result.data?.message || 'Numéro vérifié avec succès !';
modalMessageType = 'success';
data.user.phoneVerified = true;
goto('/account'); // Redirect to account page after success
} else {
modalStep = 'enter_code';
modalMessage = result.data?.message || 'Code incorrect';
modalMessageType = 'error';
}
} catch (error) {
modalStep = 'error';
modalMessage = 'Erreur de connexion. Veuillez réessayer.';
modalMessageType = 'error';
}
}
// Close modal
function closeModal() {
showConfirmationModal = false;
modalStep = 'confirm';
modalMessage = '';
modalMessageType = null;
verificationCode = '';
}
</script>
<h1 class="card-title mb-6 text-2xl">{m.settings()}</h1>
<!-- Profile Picture Section -->
<div class="mb-8 flex items-center gap-6">
<div class="avatar">
<div class="h-24 w-24 rounded-full">
{#if data.user.hasProfilePicture}
<img
src="/api/image/profile/{data.user.id}?t={$profilePictureTimestamp}"
alt={data.user.username}
class="h-full w-full object-cover"
/>
{:else}
<div class="bg-base-300 flex h-full w-full items-center justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/50 h-12 w-12"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
</div>
{/if}
</div>
</div>
<div class="flex-1">
<h2 class="text-xl font-semibold">{m.hello_user({ username: data.user.username })}</h2>
<p class="text-base-content/70">{data.user.firstname} {data.user.lastname}</p>
</div>
</div>
<!-- TODO DELETE -->
<h4>{displayLol}</h4>
{#key lol}
<h2>{lol}</h2>
{/key}
<button
onclick={() => {
lol = 'button clicked!';
console.log('lol is now:', lol);
}}
>
Test lol update
</button>
{#if selectedFile}
<h2>{selectedFile.name}</h2>
{:else}
<h2>pas de file name</h2>
{/if}
<!-- Profile Picture Upload Form -->
<div class="divider">{m.profile_picture()}</div>
<form
method="post"
action="?/uploadProfilePicture"
enctype="multipart/form-data"
use:enhance={() => {
return ({ result }) => {
if (result.type === 'success') {
// Update global timestamp to force image refresh everywhere
refreshProfilePicture();
data.user.hasProfilePicture = true;
//selectedFile = null;
}
};
}}
class="space-y-4"
>
<div class="form-control">
<label class="label" for="profilePicture">
<span class="label-text">{m.change_profile_picture()}</span>
</label>
<div class="relative">
<input
type="file"
id="profilePicture"
name="profilePicture"
accept="image/*"
onchange={handleFileChange}
style="position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0;"
/>
<label for="profilePicture" class="btn btn-outline w-full cursor-pointer">
{selectedFile ? selectedFile.name : m.select_photo()}
</label>
</div>
<span class="label label-text-alt">{m.accepted_formats()}</span>
</div>
<button type="submit" class="btn btn-primary" disabled={!selectedFile}>
<svg
xmlns="http://www.w3.org/2000/svg"
class="mr-2 h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
/>
</svg>
{m.update_photo()}
</button>
</form>
<!-- Email Verification Section -->
<div class="divider">{m.email_verification()}</div>
<div class="space-y-4">
{#if data.user.emailVerified}
<div class="alert alert-success">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>{m.your_email_verified({ email: data.user.email })}</span>
</div>
{:else}
<div class="alert alert-warning">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16c-.77.833.192 2.5 1.732 2.5z"
/>
</svg>
<div>
<p>
{m.your_email_not_verified({ email: data.user.email })}
</p>
<p class="text-sm opacity-75">
{m.verify_email_access()}
</p>
</div>
</div>
<form
method="post"
action="?/resendVerificationEmail"
use:enhance={() => {
isResendingEmail = true;
emailMessage = null;
emailMessageType = null;
return ({ result }) => {
isResendingEmail = false;
if (result.type === 'success') {
emailMessage =
(result.data as any)?.message || 'Email de confirmation envoyé avec succès';
emailMessageType = 'success';
} else if (result.type === 'failure') {
emailMessage = (result.data as any)?.message || "Erreur lors de l'envoi de l'email";
emailMessageType = 'error';
}
// Clear message after 5 seconds
setTimeout(() => {
emailMessage = null;
emailMessageType = null;
}, 5000);
};
}}
class="mt-4"
>
<button type="submit" class="btn btn-outline btn-primary" disabled={isResendingEmail}>
{#if isResendingEmail}
<span class="loading loading-spinner loading-sm mr-2"></span>
{m.sending_in_progress()}
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
class="mr-2 h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
/>
</svg>
{m.resend_verification_email()}
{/if}
</button>
</form>
{#if emailMessage}
<div class="alert {emailMessageType === 'success' ? 'alert-success' : 'alert-error'} mt-4">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
{#if emailMessageType === 'success'}
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
{:else}
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
{/if}
</svg>
<span>{emailMessage}</span>
</div>
{/if}
{/if}
</div>
<!-- Phone Number Verification Section -->
<div class="divider">{m.phone_verification()}</div>
<div class="space-y-4">
<!-- Phone Number Input Form -->
<div class="space-y-4">
<div class="form-control">
<label class="label" for="phoneNumber">
<span class="label-text">{m.phone_number()}</span>
</label>
<div class="flex gap-2">
<!-- Country Code Selector -->
<select
bind:value={countryCode}
class="select select-bordered w-32 flex-shrink-0"
aria-label="Country code"
>
{#each sortedCountryCodes as country}
<option value={country.code}>
{country.flag}
{country.code}
</option>
{/each}
</select>
<!-- Phone Number Input -->
<input
type="tel"
id="phoneNumber"
bind:value={phoneNumber}
oninput={handlePhoneInput}
placeholder="079 548 17 17"
class="input input-bordered flex-1"
/>
</div>
<span class="label label-text-alt">
{#if data.user.telephone}
{m.current_number({ phone: data.user.telephone })}
{:else}
{m.enter_phone_number()}
{/if}
</span>
</div>
</div>
<!-- Phone Verification Status -->
{#if data.user.telephone && data.user.phoneVerified}
<div class="alert alert-success">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>{m.your_phone_verified({ phone: data.user.telephone })}</span>
</div>
{:else if data.user.telephone && !data.user.phoneVerified}
<div class="alert alert-warning">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16c-.77.833.192 2.5 1.732 2.5z"
/>
</svg>
<div>
<p>
{m.your_phone_not_verified({ phone: data.user.telephone })}
</p>
<p class="text-sm opacity-75">
{m.verify_phone_access()}
</p>
</div>
</div>
{:else}
<div class="alert alert-info">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>{m.add_phone_verification()}</span>
</div>
{/if}
<!-- Send Verification Code Button -->
{#if phoneNumber.trim()}
<button
type="button"
class="btn btn-outline btn-primary"
onclick={handleSendVerificationCodeUI}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="mr-2 h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
/>
</svg>
{fullPhoneNumber === data.user.telephone
? m.resend_verification_code()
: m.send_verification_code()}
</button>
{/if}
</div>
<!-- Logout Section -->
<div class="divider">{m.actions()}</div>
<form method="post" action="?/logout" use:enhance>
<button class="btn btn-error">
<svg
xmlns="http://www.w3.org/2000/svg"
class="mr-2 h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"
/>
</svg>
{m.sign_out()}
</button>
</form>
<!-- Phone Verification Modal -->
{#if showConfirmationModal}
<div class="modal modal-open">
<div class="modal-box">
{#if modalStep === 'confirm'}
<h3 class="mb-4 text-lg font-bold">Confirmer l'envoi du code de vérification</h3>
<div class="py-4">
<p class="mb-2">
Vous êtes sur le point d'envoyer un code de vérification SMS au numéro:
</p>
<p class="text-primary text-lg font-bold">{tempPhoneNumber}</p>
{#if tempPhoneNumber !== data.user.telephone && data.user.telephone}
<div class="alert alert-warning mt-4">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16c-.77.833.192 2.5 1.732 2.5z"
/>
</svg>
<div>
<p class="font-semibold">Attention: Changement de numéro</p>
<p class="text-sm">
Votre numéro actuel ({data.user.telephone}) sera remplacé par ce nouveau numéro.
</p>
</div>
</div>
{/if}
</div>
<!-- reCAPTCHA widget -->
<div
class="g-recaptcha"
data-sitekey="6LeYV3QrAAAAAGWnwNjNXoOXvrCnOqTKIzgeEWUU"
data-callback="onRecaptchaValidated"
></div>
<div class="modal-action">
<button class="btn btn-ghost" onclick={closeModal}>Annuler</button>
<button class="btn btn-primary" onclick={confirmAndSendCode} disabled={!captchaToken}>
<svg
xmlns="http://www.w3.org/2000/svg"
class="mr-2 h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
/>
</svg>
Confirmer et envoyer
</button>
</div>
{:else if modalStep === 'sending'}
<h3 class="mb-4 text-lg font-bold">Envoi en cours...</h3>
<div class="py-4 text-center">
<span class="loading loading-spinner loading-lg"></span>
<p class="mt-4">{modalMessage}</p>
</div>
{:else if modalStep === 'enter_code'}
<h3 class="mb-4 text-lg font-bold">Saisir le code de vérification</h3>
<div class="py-4">
{#if modalMessage && modalMessageType === 'success'}
<div class="alert alert-success mb-4">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>{modalMessage}</span>
</div>
{:else if modalMessage && modalMessageType === 'error'}
<div class="alert alert-error mb-4">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>{modalMessage}</span>
</div>
{/if}
<p class="mb-4">
Un code à 6 chiffres a été envoyé au numéro <strong>{tempPhoneNumber}</strong>
</p>
<div class="form-control">
<label class="label" for="modalVerificationCode">
<span class="label-text">Code de vérification</span>
</label>
<input
type="text"
id="modalVerificationCode"
bind:value={verificationCode}
placeholder="123456"
maxlength="6"
inputmode="numeric"
class="input input-bordered w-full"
/>
</div>
</div>
<div class="modal-action">
<button class="btn btn-ghost" onclick={closeModal}>Annuler</button>
<button
class="btn btn-primary"
disabled={verificationCode.length !== 6}
onclick={verifyCode}
>
Vérifier le code
</button>
</div>
{:else if modalStep === 'verifying'}
<h3 class="mb-4 text-lg font-bold">Vérification en cours...</h3>
<div class="py-4 text-center">
<span class="loading loading-spinner loading-lg"></span>
<p class="mt-4">{modalMessage}</p>
</div>
{:else if modalStep === 'success'}
<h3 class="mb-4 text-lg font-bold">Succès !</h3>
<div class="py-4">
<div class="alert alert-success">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>{modalMessage}</span>
</div>
</div>
{:else if modalStep === 'error'}
<h3 class="mb-4 text-lg font-bold">Erreur</h3>
<div class="py-4">
<div class="alert alert-error">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>{modalMessage}</span>
</div>
</div>
<div class="modal-action">
<button class="btn btn-primary" onclick={closeModal}>Fermer</button>
</div>
{/if}
</div>
<div
class="modal-backdrop"
role="button"
tabindex="0"
onclick={modalStep === 'sending' || modalStep === 'verifying' ? undefined : closeModal}
onkeydown={(e) =>
e.key === 'Escape' && modalStep !== 'sending' && modalStep !== 'verifying' && closeModal()}
></div>
</div>
{/if}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment