Skip to content

Commit 9231768

Browse files
authored
V3 login UI (#215)
* fix: show login error * fix: show shignup error * chore: pre-commit
1 parent 62a7f23 commit 9231768

25 files changed

+877
-1264
lines changed

.env.local.example

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ SAQ_BACKGROUND_WORKERS=1
3030
SAQ_CONCURRENCY=1
3131

3232
# Frontend Configuration
33+
VITE_USE_SERVER_LIFESPAN=True
34+
VITE_HOT_RELOAD=True
35+
VITE_DEV_MODE=True
3336
VITE_HOST=localhost
3437
VITE_PORT=3006
3538
ALLOWED_CORS_ORIGINS=["localhost:3006","localhost:8080","localhost:8000"]
@@ -40,7 +43,7 @@ APP_SCRATCH_PATH=/tmp/app
4043
# Email Configuration (SMTP)
4144
EMAIL_ENABLED=true # Set to true to enable email sending
4245
EMAIL_SMTP_HOST=localhost # For MailHog: localhost, for production: your SMTP host
43-
EMAIL_SMTP_PORT=1025 # For MailHog: 1025, for production: 587 (TLS) or 465 (SSL)
46+
EMAIL_SMTP_PORT=11025 # For MailHog: 11025, for production: 587 (TLS) or 465 (SSL)
4447
EMAIL_SMTP_USER= # MailHog doesn't require auth, leave empty for dev
4548
EMAIL_SMTP_PASSWORD= # MailHog doesn't require auth, leave empty for dev
4649
EMAIL_USE_TLS=false # MailHog doesn't use TLS, set true for production

src/js/src/components/auth/login.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,10 @@ export function UserLoginForm() {
3030

3131
const onSubmit = async (data: LoginFormData) => {
3232
try {
33-
// TODO: Fix/verify login
3433
await login(data.email, data.password)
3534
navigate({ to: "/home" })
3635
} catch (error) {
37-
form.setError("root", {
38-
message: "Invalid credentials",
39-
})
36+
console.error("[DEBUG] Login error:", error)
4037
}
4138
}
4239

src/js/src/components/auth/signup.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { useAuthStore } from "@/lib/auth"
66
import { zodResolver } from "@hookform/resolvers/zod"
77
import { useNavigate } from "@tanstack/react-router"
88
import { useForm } from "react-hook-form"
9+
// import { toast } from "sonner"
910
import { z } from "zod"
1011

1112
const signupSchema = z
@@ -40,15 +41,19 @@ export function UserSignupForm() {
4041

4142
const onSubmit = async (data: SignupFormData) => {
4243
try {
43-
// TODO: verify registration
44-
await accountRegister({
44+
const response = await accountRegister({
4545
body: { email: data.email, password: data.password, name: data.name },
4646
})
47-
// navigate({ to: "/login" });
47+
48+
if (response.status === 201) {
49+
navigate({ to: "/login" })
50+
return
51+
}
52+
53+
// Getting status 500 for BE for validation errors. Not showing toast for now.
54+
// toast.error(response.error?.title || "Signup failed")
4855
} catch (error) {
49-
form.setError("root", {
50-
message: "Signup failed",
51-
})
56+
console.error("[DEBUG] Signup error:", error)
5257
}
5358
}
5459

src/js/src/layouts/public-layout.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
import { useTheme } from "@/lib/theme-context"
12
import { Outlet } from "@tanstack/react-router"
3+
import { Toaster } from "sonner"
24

35
export function PublicLayout() {
6+
const { theme } = useTheme()
7+
48
return (
59
<div className="flex min-h-screen flex-col">
10+
<Toaster richColors theme={theme} position="top-right" />
611
<main className="flex flex-1">
712
<Outlet />
813
</main>

src/js/src/lib/auth.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { accountLogin, accountLogout, accountProfile } from "@/lib/api/sdk.gen"
22
import type { Team, User } from "@/lib/api/types.gen"
3+
import { toast } from "sonner"
34
import { create } from "zustand"
45
import { persist } from "zustand/middleware"
56

@@ -27,18 +28,27 @@ export const useAuthStore = create<AuthState>()(
2728
login: async (email: string, password: string) => {
2829
set({ isLoading: true })
2930
try {
30-
// First make the login request
31-
await accountLogin({ body: { username: email, password } })
31+
// Login request
32+
const response = await accountLogin({ body: { username: email, password } })
3233

33-
// Add a small delay to ensure the cookie is set
34-
await new Promise((resolve) => setTimeout(resolve, 100))
34+
if (response.status === 201) {
35+
// Add a small delay to ensure the cookie is set
36+
await new Promise((resolve) => setTimeout(resolve, 100))
3537

36-
// Then verify the authentication by getting the profile
37-
const { data: user } = await accountProfile()
38-
set({ user, isAuthenticated: true })
38+
// Verify the authentication by getting the profile
39+
const { data: user } = await accountProfile()
40+
// TODO: Maybe add a check for user here?
41+
set({ user, isAuthenticated: true })
42+
return
43+
}
44+
45+
set({ user: null, currentTeam: null, isAuthenticated: false })
46+
toast.error(response.error?.title || "Login failed")
3947
} catch (error) {
4048
set({ user: null, currentTeam: null, isAuthenticated: false })
41-
throw error
49+
toast.error("An error occurred", {
50+
description: error instanceof Error ? error.message : "Unknown error",
51+
})
4252
} finally {
4353
set({ isLoading: false })
4454
}

src/js/src/openapi.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,7 +1524,7 @@
15241524
"name": "sortOrder",
15251525
"in": "query",
15261526
"schema": {
1527-
"type": ["string", "null"],
1527+
"type": ["null", "string"],
15281528
"enum": ["asc", "desc", null],
15291529
"title": "Field to search",
15301530
"default": "desc"
@@ -1796,7 +1796,7 @@
17961796
"name": "sortOrder",
17971797
"in": "query",
17981798
"schema": {
1799-
"type": ["string", "null"],
1799+
"type": ["null", "string"],
18001800
"enum": ["asc", "desc", null],
18011801
"title": "Field to search",
18021802
"default": "asc"
@@ -3530,7 +3530,7 @@
35303530
"name": "sortOrder",
35313531
"in": "query",
35323532
"schema": {
3533-
"type": ["string", "null"],
3533+
"type": ["null", "string"],
35343534
"enum": ["asc", "desc", null],
35353535
"title": "Field to search",
35363536
"default": "desc"

src/py/app/server/templates/emails/email_verification.html.j2

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,18 @@
7373
<div class="content">
7474
<h2>Welcome{{ ' ' + user.name if user.name else '' }}!</h2>
7575
<p>Thanks for signing up for {{ app_name }}. To complete your registration, please verify your email address by clicking the button below:</p>
76-
76+
7777
<div style="text-align: center;">
7878
<a href="{{ verification_url }}" class="button">Verify Email Address</a>
7979
</div>
80-
80+
8181
<p>Or copy and paste this URL into your browser:</p>
8282
<div class="url-box">{{ verification_url }}</div>
83-
83+
8484
<p><strong>This link will expire in {{ expires_in_hours }} hours.</strong></p>
85-
85+
8686
<p>If you didn't create an account with {{ app_name }}, please ignore this email.</p>
87-
87+
8888
<p>Need help? Contact our support team if you have any questions.</p>
8989
</div>
9090
<div class="footer">
@@ -93,4 +93,4 @@
9393
</div>
9494
</div>
9595
</body>
96-
</html>
96+
</html>

src/py/app/server/templates/emails/email_verification.txt.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ Best regards,
1616
{{ app_name }} Team
1717

1818
--
19-
This is an automated email. Please do not reply to this message.
19+
This is an automated email. Please do not reply to this message.

src/py/app/server/templates/emails/team_invitation.html.j2

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,22 @@
8585
</div>
8686
<div class="content">
8787
<h2>Join a team on {{ app_name }}</h2>
88-
88+
8989
<p><strong>{{ inviter_name }}</strong> has invited you to join their team:</p>
90-
90+
9191
<div class="team-info">
9292
<div class="team-name">{{ team_name }}</div>
9393
</div>
94-
94+
9595
<p>By joining this team, you'll be able to collaborate with other team members, share resources, and work together on {{ app_name }}.</p>
96-
96+
9797
<div style="text-align: center;">
9898
<a href="{{ invitation_url }}" class="button">Accept Invitation</a>
9999
</div>
100-
100+
101101
<p>Or copy and paste this URL into your browser:</p>
102102
<div class="url-box">{{ invitation_url }}</div>
103-
103+
104104
<p>If you don't want to join this team or don't know {{ inviter_name }}, you can safely ignore this email.</p>
105105
</div>
106106
<div class="footer">
@@ -109,4 +109,4 @@
109109
</div>
110110
</div>
111111
</body>
112-
</html>
112+
</html>

src/py/app/server/templates/emails/team_invitation.txt.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ If you don't want to join this team or don't know {{ inviter_name }}, you can sa
1313

1414
--
1515
This invitation was sent to you by {{ inviter_name }}.
16-
{{ app_name }}
16+
{{ app_name }}

0 commit comments

Comments
 (0)