Skip to content
Open
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
6 changes: 3 additions & 3 deletions assets/vue/components/log-in/LoginForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ const submit = () => {
<div class="grid gap-3">
<div class="flex items-center">
<Label for="password">Password</Label>
<a
href="#"
<Link
navigate="/forgot_password"
class="ml-auto text-sm underline-offset-4 hover:underline"
>
Forgot your password?
</a>
</Link>
</div>
<Input id="password" type="password" v-model="form.password" required />
</div>
Expand Down
9 changes: 6 additions & 3 deletions assets/vue/components/registration/RegistrationForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const passwordField = form.field("password");
</div>
<div class="grid gap-6">
<div class="grid gap-3">
<Label for="name" mandatory> Name </Label>
<Label for="name" mandatory>Name</Label>
<Input
type="text"
placeholder="John Doe"
Expand Down Expand Up @@ -79,11 +79,14 @@ const passwordField = form.field("password");
</div>
<Button
type="button"
class="w-full"
:disabled="!form.isValid.value || form.isValidating.value"
:aria-busy="form.isValidating.value"
@click="form.submit()"
class="w-full"
>
{{ form.isValidating.value ? "Validating..." : "Register" }}
<span role="status" aria-live="polite">
{{ form.isValidating.value ? "Validating..." : "Register" }}
</span>
</Button>
<div
class="after:border-border relative text-center text-sm after:absolute after:inset-0 after:top-1/2 after:z-0 after:flex after:items-center after:border-t"
Expand Down
5 changes: 3 additions & 2 deletions assets/vue/pages/log-in/UserLogin.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { GalleryVerticalEnd } from "lucide-vue-next";
import { Link } from "live_vue";
import LoginForm from "@/components/log-in/LoginForm.vue";

const URL = import.meta.env.VITE_PHOENIX_URL;
Expand All @@ -9,14 +10,14 @@ const URL = import.meta.env.VITE_PHOENIX_URL;
<div class="grid min-h-svh lg:grid-cols-2">
<div class="flex flex-col gap-4 p-6 md:p-10">
<div class="flex justify-center gap-2 md:justify-start">
<a href="#" class="flex items-center gap-2 font-medium">
<Link navigate="/" class="flex items-center gap-2 font-medium">
<div
class="flex h-6 w-6 items-center justify-center rounded-md bg-primary text-primary-foreground"
>
<GalleryVerticalEnd class="size-4" />
</div>
Katana is your place
</a>
</Link>
</div>
<div class="flex flex-1 items-center justify-center">
<div class="w-full max-w-xs">
Expand Down
5 changes: 3 additions & 2 deletions assets/vue/pages/registration/UserRegistration.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { GalleryVerticalEnd } from "lucide-vue-next";
import { Link } from "live_vue";
import RegistrationForm from "@/components/registration/RegistrationForm.vue";

const props = defineProps<{
Expand All @@ -19,14 +20,14 @@ const URL = import.meta.env.VITE_PHOENIX_URL;
</div>
<div class="flex flex-col gap-4 p-6 md:p-10">
<div class="flex justify-center gap-2 md:justify-start">
<a href="#" class="flex items-center gap-2 font-medium">
<Link navigate="/" class="flex items-center gap-2 font-medium">
<div
class="flex h-6 w-6 items-center justify-center rounded-md bg-primary text-primary-foreground"
>
<GalleryVerticalEnd class="size-4" />
</div>
Welcome to Katana
</a>
</Link>
</div>
<div class="flex flex-1 items-center justify-center">
<div class="w-full max-w-xs">
Expand Down
4 changes: 2 additions & 2 deletions lib/katana/accounts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,11 @@ defmodule Katana.Accounts do

## Examples

iex> deliver_user_reset_password_instructions(user, &url(~p"/users/reset_password/#{&1}"))
iex> deliver_reset_password_instructions(user, &url(~p"/users/reset_password/#{&1}"))
{:ok, %{to: ..., body: ...}}

"""
def deliver_user_reset_password_instructions(%User{} = user, reset_password_url_fun)
def deliver_reset_password_instructions(%User{} = user, reset_password_url_fun)
when is_function(reset_password_url_fun, 1) do
{encoded_token, user_token} = UserToken.build_email_token(user, "reset_password")
Repo.insert!(user_token)
Expand Down
2 changes: 1 addition & 1 deletion lib/katana/accounts/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Katana.Accounts.User do

@registration_fields ~w(name email password)a

@derive {LiveVue.Encoder, except: [:hashed_password, :current_password, :confirmed_at]}
@derive {LiveVue.Encoder, except: [:hashed_password, :confirmed_at]}
schema "users" do
field :name, :string
field :email, :string
Expand Down
50 changes: 0 additions & 50 deletions lib/katana_web/live/auth/user_forgot_password_live.ex

This file was deleted.

89 changes: 0 additions & 89 deletions lib/katana_web/live/auth/user_reset_password_live.ex

This file was deleted.

23 changes: 23 additions & 0 deletions lib/katana_web/live/forgot-password/ForgotPassword.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script setup lang="ts">
import { GalleryVerticalEnd } from "lucide-vue-next";
import { Link } from "live_vue";
import ForgotPasswordForm from "./components/ForgotPasswordForm.vue";
</script>

<template>
<div class="min-h-svh flex items-center justify-center p-6">
<div class="w-full max-w-md space-y-8">
<div class="flex justify-center">
<Link navigate="/" class="flex items-center gap-2 font-medium">
<div
class="flex h-8 w-8 items-center justify-center rounded-md bg-primary text-primary-foreground"
>
<GalleryVerticalEnd class="size-5" />
</div>
Katana
</Link>
</div>
<ForgotPasswordForm />
</div>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<script setup lang="ts">
import { Ref, ref } from "vue";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Link } from "live_vue";

const form: Ref<{ email: string }> = ref({
email: "",
});
</script>

<template>
<form class="flex flex-col gap-6">
<div class="flex flex-col items-center gap-2 text-center">
<h1 class="text-2xl font-bold">Esqueceu-se da sua palavra-passe?</h1>
<p class="text-muted-foreground text-sm">
Introduza o endereço de email associado à sua conta e enviaremos um
link para redefinir a sua palavra-passe
</p>
</div>
<div class="grid gap-6">
<div class="grid gap-3">
<Label for="email">Email</Label>
<Input
id="email"
type="email"
placeholder="mail@coderdojobraga.org"
v-model="form.email"
required
/>
</div>
<Button
type="button"
@click="$live.pushEvent('send_email', { user: { email: form.email } })"
:disabled="!form.email"
class="w-full"
>
Enviar link de redefinição
</Button>
</div>
<div class="text-center text-sm">
Lembra-se da sua palavra-passe?
<Link navigate="/users/log_in" class="underline underline-offset-4">
Iniciar sessão
</Link>
</div>
</form>
</template>
32 changes: 32 additions & 0 deletions lib/katana_web/live/forgot-password/forgot_password_live.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule KatanaWeb.ForgotPasswordLive do
use KatanaWeb, {:live_view, :root}

alias Katana.Accounts

def render(assigns) do
~H"""
<.vue v-component="ForgotPassword" v-socket={@socket} />
"""
end

def mount(_params, _session, socket) do
{:ok, assign(socket, form: to_form(%{}, as: "user"))}
end

def handle_event("send_email", %{"user" => %{"email" => email}}, socket) do
if user = Accounts.get_user_by_email(email) do
Accounts.deliver_reset_password_instructions(
user,
&url(~p"/reset_password/#{&1}")
)
end

{:noreply,
socket
|> put_flash(
:info,
"If your email is in our system, you will receive instructions to reset your password shortly."
)
|> redirect(to: ~p"/")}
end
end
27 changes: 27 additions & 0 deletions lib/katana_web/live/reset-password/ResetPassword.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script setup lang="ts">
import { GalleryVerticalEnd } from "lucide-vue-next";
import { Form, Link } from "live_vue";
import ResetPasswordForm from "./components/ResetPasswordForm.vue";

const props = defineProps<{
form: Form<ResetPasswordFields>
}>();
</script>

<template>
<div class="min-h-svh flex items-center justify-center p-6">
<div class="w-full max-w-md space-y-8">
<div class="flex justify-center">
<Link navigate="/" class="flex items-center gap-2 font-medium">
<div
class="flex h-8 w-8 items-center justify-center rounded-md bg-primary text-primary-foreground"
>
<GalleryVerticalEnd class="size-5" />
</div>
Katana
</Link>
</div>
<ResetPasswordForm :form="props.form" />
</div>
</div>
</template>
Loading