Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ GEM
date
stringio
public_suffix (6.0.2)
puma (7.0.1)
puma (7.0.2)
nio4r (~> 2.0)
raabro (1.4.0)
racc (1.8.1)
Expand Down Expand Up @@ -348,7 +348,7 @@ GEM
fugit (~> 1.11.0)
railties (>= 7.1)
thor (>= 1.3.1)
sorbet-runtime (0.6.12495)
sorbet-runtime (0.6.12507)
sqlite3 (2.7.3-aarch64-linux-gnu)
sqlite3 (2.7.3-aarch64-linux-musl)
sqlite3 (2.7.3-arm-linux-gnu)
Expand All @@ -372,9 +372,9 @@ GEM
timeout (0.4.3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (3.1.5)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.1.0)
uri (1.0.3)
useragent (0.16.11)
vite_rails (3.0.19)
Expand Down
112 changes: 53 additions & 59 deletions app/frontend/components/delete-user.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import { useForm } from "@inertiajs/svelte"
import type { FormComponentSlotProps } from "@inertiajs/core"
import { Form } from "@inertiajs/svelte"

import HeadingSmall from "@/components/heading-small.svelte"
import InputError from "@/components/input-error.svelte"
Expand All @@ -10,26 +11,6 @@
import { usersPath } from "@/routes"

let passwordInput: HTMLInputElement | null = null

const form = useForm({
password_challenge: "",
})

const deleteUser = (e: Event) => {
e.preventDefault()

$form.delete(usersPath(), {
preserveScroll: true,
onSuccess: () => closeModal(),
onError: () => passwordInput?.focus(),
onFinish: () => $form.reset(),
})
}

const closeModal = () => {
$form.clearErrors()
$form.reset()
}
</script>

<div class="space-y-6">
Expand All @@ -49,47 +30,60 @@
<Button variant="destructive">Delete account</Button>
</Dialog.Trigger>
<Dialog.Content>
<form class="space-y-6" on:submit={deleteUser}>
<Dialog.Header class="space-y-3">
<Dialog.Title>
Are you sure you want to delete your account?
</Dialog.Title>
<Dialog.Description>
Once your account is deleted, all of its resources and data will
also be permanently deleted. Please enter your password to confirm
you would like to permanently delete your account.
</Dialog.Description>
</Dialog.Header>
<Form
method="delete"
action={usersPath()}
options={{
preserveScroll: true,
}}
onError={() => passwordInput?.focus()}
resetOnSuccess
class="space-y-6"
>
{#snippet children({
errors,
processing,
resetAndClearErrors,
}: FormComponentSlotProps)}
<Dialog.Header class="space-y-3">
<Dialog.Title>
Are you sure you want to delete your account?
</Dialog.Title>
<Dialog.Description>
Once your account is deleted, all of its resources and data will
also be permanently deleted. Please enter your password to
confirm you would like to permanently delete your account.
</Dialog.Description>
</Dialog.Header>

<div class="grid gap-2">
<Label for="password_challenge" class="sr-only">Password</Label>
<Input
id="password_challenge"
type="password"
name="password_challenge"
bind:ref={passwordInput}
bind:value={$form.password_challenge}
placeholder="Password"
/>
<InputError message={$form.errors.password_challenge} />
</div>
<div class="grid gap-2">
<Label for="password_challenge" class="sr-only">Password</Label>
<Input
id="password_challenge"
type="password"
name="password_challenge"
bind:ref={passwordInput}
placeholder="Password"
/>
<InputError message={errors.password_challenge} />
</div>

<Dialog.Footer class="gap-2">
<Dialog.Close>
{#snippet child()}
<Button variant="secondary" onclick={closeModal}>Cancel</Button>
{/snippet}
</Dialog.Close>
<Dialog.Footer class="gap-2">
<Dialog.Close>
{#snippet child()}
<Button
variant="secondary"
onclick={() => resetAndClearErrors()}>Cancel</Button
>
{/snippet}
</Dialog.Close>

<Button
type="submit"
variant="destructive"
disabled={$form.processing}
>
Delete account
</Button>
</Dialog.Footer>
</form>
<Button type="submit" variant="destructive" disabled={processing}>
Delete account
</Button>
</Dialog.Footer>
{/snippet}
</Form>
</Dialog.Content>
</Dialog.Root>
</div>
Expand Down
124 changes: 57 additions & 67 deletions app/frontend/pages/identity/password_resets/edit.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import { useForm } from "@inertiajs/svelte"
import type { FormComponentSlotProps } from "@inertiajs/core"
import { Form } from "@inertiajs/svelte"
import { LoaderCircle } from "@lucide/svelte"

import InputError from "@/components/input-error.svelte"
Expand All @@ -15,22 +16,6 @@
}

let { sid, email }: Props = $props()

const form = useForm({
sid,
email,
password: "",
password_confirmation: "",
})

const submit = (e: Event) => {
e.preventDefault()
$form.put(identityPasswordResetPath(), {
onFinish: () => {
$form.reset("password", "password_confirmation")
},
})
}
</script>

<svelte:head>
Expand All @@ -41,57 +26,62 @@
title="Reset password"
description="Please enter your new password below"
>
<form onsubmit={submit}>
<div class="grid gap-6">
<div class="grid gap-2">
<Label for="email">Email</Label>
<Input
id="email"
type="email"
name="email"
autocomplete="email"
bind:value={$form.email}
class="mt-1 block w-full"
readonly
/>
<InputError message={$form.errors.email} class="mt-2" />
</div>
<Form
method="put"
action={identityPasswordResetPath()}
transform={(data) => ({ ...data, sid, email })}
resetOnSuccess={["password", "password_confirmation"]}
>
{#snippet children({ errors, processing }: FormComponentSlotProps)}
<div class="grid gap-6">
<div class="grid gap-2">
<Label for="email">Email</Label>
<Input
id="email"
name="email"
type="email"
autocomplete="email"
value={email}
class="mt-1 block w-full"
readonly
/>
<InputError message={errors.email} class="mt-2" />
</div>

<div class="grid gap-2">
<Label for="password">Password</Label>
<Input
id="password"
type="password"
name="password"
autocomplete="new-password"
bind:value={$form.password}
class="mt-1 block w-full"
autofocus
placeholder="Password"
/>
<InputError message={$form.errors.password} />
</div>
<div class="grid gap-2">
<Label for="password">Password</Label>
<Input
id="password"
name="password"
type="password"
autocomplete="new-password"
class="mt-1 block w-full"
autofocus
placeholder="Password"
/>
<InputError message={errors.password} />
</div>

<div class="grid gap-2">
<Label for="password_confirmation">Confirm Password</Label>
<Input
id="password_confirmation"
type="password"
name="password_confirmation"
autocomplete="new-password"
bind:value={$form.password_confirmation}
class="mt-1 block w-full"
placeholder="Confirm password"
/>
<InputError message={$form.errors.password_confirmation} />
</div>
<div class="grid gap-2">
<Label for="password_confirmation">Confirm Password</Label>
<Input
id="password_confirmation"
name="password_confirmation"
type="password"
autocomplete="new-password"
class="mt-1 block w-full"
placeholder="Confirm password"
/>
<InputError message={errors.password_confirmation} />
</div>

<Button type="submit" class="mt-4 w-full" disabled={$form.processing}>
{#if $form.processing}
<LoaderCircle class="h-4 w-4 animate-spin" />
{/if}
Reset password
</Button>
</div>
</form>
<Button type="submit" class="mt-4 w-full" disabled={processing}>
{#if processing}
<LoaderCircle class="h-4 w-4 animate-spin" />
{/if}
Reset password
</Button>
</div>
{/snippet}
</Form>
</AuthLayout>
59 changes: 26 additions & 33 deletions app/frontend/pages/identity/password_resets/new.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import { useForm } from "@inertiajs/svelte"
import type { FormComponentSlotProps } from "@inertiajs/core"
import { Form } from "@inertiajs/svelte"
import { LoaderCircle } from "@lucide/svelte"

import InputError from "@/components/input-error.svelte"
Expand All @@ -9,15 +10,6 @@
import { Label } from "@/components/ui/label"
import AuthLayout from "@/layouts/auth-layout.svelte"
import { identityPasswordResetPath, signInPath } from "@/routes"

const form = useForm({
email: "",
})

const submit = (e: Event) => {
e.preventDefault()
$form.post(identityPasswordResetPath())
}
</script>

<svelte:head>
Expand All @@ -29,30 +21,31 @@
description="Enter your email to receive a password reset link"
>
<div class="space-y-6">
<form onsubmit={submit}>
<div class="grid gap-2">
<Label for="email">Email address</Label>
<Input
id="email"
type="email"
name="email"
autocomplete="off"
bind:value={$form.email}
autofocus
placeholder="[email protected]"
/>
<InputError message={$form.errors.email} />
</div>
<Form method="post" action={identityPasswordResetPath()}>
{#snippet children({ errors, processing }: FormComponentSlotProps)}
<div class="grid gap-2">
<Label for="email">Email address</Label>
<Input
id="email"
name="email"
type="email"
autocomplete="off"
autofocus
placeholder="[email protected]"
/>
<InputError message={errors.email} />
</div>

<div class="my-6 flex items-center justify-start">
<Button type="submit" class="w-full" disabled={$form.processing}>
{#if $form.processing}
<LoaderCircle class="h-4 w-4 animate-spin" />
{/if}
Email password reset link
</Button>
</div>
</form>
<div class="my-6 flex items-center justify-start">
<Button type="submit" class="w-full" disabled={processing}>
{#if processing}
<LoaderCircle class="h-4 w-4 animate-spin" />
{/if}
Email password reset link
</Button>
</div>
{/snippet}
</Form>

<div class="text-muted-foreground space-x-1 text-center text-sm">
<span>Or, return to</span>
Expand Down
Loading