feat: add new UI components and improve existing ones

- Introduced `Field` and `Label` components for better form handling.
- Refactored `Input` and `Textarea` components to use forward refs and improved styling.
- Updated `PendingSubmitButton` to use the new `Button` component.
- Enhanced `Skeleton` component for better layout handling.
- Revamped `Toast` component to support live regions and improved accessibility.
- Updated sidebar configuration to use typed icons.
- Added phase 3 UI boundary checks to prevent usage of deprecated imports.
- Implemented new authentication action handler for better cookie management.
- Improved setup logic for freelancer accounts with repair functionality.
This commit is contained in:
Poyraz
2026-07-10 22:47:02 +03:00
parent ae8fa1425c
commit 24fcdf9a77
28 changed files with 1183 additions and 943 deletions
+42 -33
View File
@@ -1,41 +1,32 @@
'use server'
import { revalidatePath } from 'next/cache'
import { headers } from 'next/headers'
import { redirect } from 'next/navigation'
import { auth } from '@/server/auth/auth'
import { callAuthAction } from '@/server/auth/action-handler'
import { getProfileByAuthUserId } from '@/server/auth/session'
import { getFirstFreelancerSetupState, recordAuthAuditEvent } from '@/server/auth/setup'
import {
getFirstFreelancerSetupState,
recordAuthAuditEvent,
repairFirstFreelancerSetupForEmail,
} from '@/server/auth/setup'
import { getDefaultDisplayName, parseAuthCredentials } from '@/server/auth/validation'
const genericLoginError = 'E-posta veya şifre hatalı.'
const genericLoginError = 'E-posta veya \u015fifre hatal\u0131.'
type SignInEmailResult = Awaited<ReturnType<typeof auth.api.signInEmail>>
type SignUpEmailResult = Awaited<ReturnType<typeof auth.api.signUpEmail>>
export async function login(formData: FormData) {
const credentials = parseAuthCredentials(formData)
let redirectTarget = '/'
let result: SignInEmailResult
try {
const result = await auth.api.signInEmail({
body: {
email: credentials.email,
password: credentials.password,
rememberMe: true,
},
result = await callAuthAction<SignInEmailResult>('/sign-in/email', {
email: credentials.email,
password: credentials.password,
rememberMe: true,
})
const profile = getProfileByAuthUserId(result.user.id)
if (!profile || profile.disabled) {
await auth.api.signOut({ headers: await headers() })
await recordAuthAuditEvent({
type: 'login_failed',
authUserId: result.user.id,
email: credentials.email,
metadata: { reason: 'missing_or_disabled_profile' },
})
redirect(`/login?error=true&message=${encodeURIComponent(genericLoginError)}`)
}
redirectTarget = profile.role === 'client' ? '/portal' : '/'
} catch {
await recordAuthAuditEvent({
type: 'login_failed',
@@ -45,6 +36,26 @@ export async function login(formData: FormData) {
redirect(`/login?error=true&message=${encodeURIComponent(genericLoginError)}`)
}
let profile = getProfileByAuthUserId(result.user.id)
if (!profile) {
repairFirstFreelancerSetupForEmail(result.user.email)
profile = getProfileByAuthUserId(result.user.id)
}
if (!profile || profile.disabled) {
await callAuthAction<{ success: boolean }>('/sign-out')
await recordAuthAuditEvent({
type: 'login_failed',
authUserId: result.user.id,
email: credentials.email,
metadata: { reason: 'missing_or_disabled_profile' },
})
redirect(`/login?error=true&message=${encodeURIComponent(genericLoginError)}`)
}
redirectTarget = profile.role === 'client' ? '/portal' : '/'
revalidatePath('/', 'layout')
redirect(redirectTarget)
}
@@ -59,7 +70,7 @@ export async function signup(formData: FormData) {
if (!setupState.available) {
redirect(
`/login?error=true&message=${encodeURIComponent(
'Kayıt kapalı. Bu Neta kurulumunda ilk freelancer hesabı zaten oluşturulmuş.',
'Kay\u0131t kapal\u0131. Bu Neta kurulumunda ilk freelancer hesab\u0131 zaten olu\u015fturulmu\u015f.',
)}`,
)
}
@@ -67,16 +78,14 @@ export async function signup(formData: FormData) {
const credentials = parseAuthCredentials(formData)
try {
await auth.api.signUpEmail({
body: {
name: getDefaultDisplayName(credentials.email),
email: credentials.email,
password: credentials.password,
rememberMe: true,
},
await callAuthAction<SignUpEmailResult>('/sign-up/email', {
name: getDefaultDisplayName(credentials.email),
email: credentials.email,
password: credentials.password,
rememberMe: true,
})
} catch (error) {
const message = error instanceof Error ? error.message : 'Kullanıcı oluşturulamadı.'
const message = error instanceof Error ? error.message : 'Kullan\u0131c\u0131 olu\u015fturulamad\u0131.'
redirect(`/register?error=true&message=${encodeURIComponent(message)}`)
}
@@ -85,7 +94,7 @@ export async function signup(formData: FormData) {
}
export async function signOut() {
await auth.api.signOut({ headers: await headers() })
await callAuthAction<{ success: boolean }>('/sign-out')
revalidatePath('/', 'layout')
redirect('/login')