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
7 changes: 0 additions & 7 deletions .eslintrc.cjs

This file was deleted.

7 changes: 0 additions & 7 deletions apps/web/.eslintrc.cjs

This file was deleted.

14 changes: 8 additions & 6 deletions apps/web/src/app/(auth)/login/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import { useState } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';

import type { FormEvent } from 'react';
import type { SyntheticEvent } from 'react';

import { IconBrandGithub, IconBrandGoogleFilled } from '@tabler/icons-react';

import { signIn } from '@formbase/auth/client';

import { Logo } from '../_components/logo';
import { Button } from '@formbase/ui/primitives/button';
import { Input } from '@formbase/ui/primitives/input';
import { Label } from '@formbase/ui/primitives/label';
Expand All @@ -20,6 +18,8 @@ import { LoadingButton } from '~/components/loading-button';
import { PasswordInput } from '~/components/password-input';
import { useSocialAuth } from '~/lib/hooks/use-social-auth';

import { Logo } from '../_components/logo';

export function Login() {
const router = useRouter();
const [formError, setFormError] = useState<string | null>(null);
Expand All @@ -33,14 +33,16 @@ export function Login() {

const displayError = formError ?? socialError;

const handleLogin = async (event: FormEvent<HTMLFormElement>) => {
const handleLogin = async (event: SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
setFormError(null);
setIsSubmitting(true);

const formData = new FormData(event.currentTarget);
const email = String(formData.get('email') ?? '');
const password = String(formData.get('password') ?? '');
const emailValue = formData.get('email');
const passwordValue = formData.get('password');
const email = typeof emailValue === 'string' ? emailValue : '';
const password = typeof passwordValue === 'string' ? passwordValue : '';

try {
const { error } = await signIn.email({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useState } from 'react';
import { useRouter } from 'next/navigation';

import type { FormEvent } from 'react';
import type { SyntheticEvent } from 'react';

import { ExclamationTriangleIcon } from '@radix-ui/react-icons';
import { toast } from 'sonner';
Expand All @@ -19,13 +19,14 @@ export function ResetPassword({ token }: { token: string }) {
const [formError, setFormError] = useState<string | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);

const handleReset = async (event: FormEvent<HTMLFormElement>) => {
const handleReset = async (event: SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
setFormError(null);
setIsSubmitting(true);

const formData = new FormData(event.currentTarget);
const newPassword = String(formData.get('password') ?? '');
const passwordValue = formData.get('password');
const newPassword = typeof passwordValue === 'string' ? passwordValue : '';

try {
const { error } = await authClient.resetPassword({
Expand All @@ -34,8 +35,9 @@ export function ResetPassword({ token }: { token: string }) {
});

if (error) {
setFormError(error.message);
toast(error.message, {
const errorMessage = error.message ?? null;
setFormError(errorMessage);
toast(errorMessage ?? 'Unable to reset password. Please try again.', {
icon: (
<ExclamationTriangleIcon className="h-5 w-5 text-destructive" />
),
Expand Down
16 changes: 8 additions & 8 deletions apps/web/src/app/(auth)/reset-password/send-reset-email.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
'use client';

import { type FormEvent, useState } from 'react';
import { useState } from 'react';
import { useRouter } from 'next/navigation';

import type { SyntheticEvent } from 'react';

import { toast } from 'sonner';

import { authClient } from '@formbase/auth/client';
Expand All @@ -16,21 +18,22 @@ export function SendResetEmail() {
const [formError, setFormError] = useState<string | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);

const handleResetRequest = async (event: FormEvent<HTMLFormElement>) => {
const handleResetRequest = async (event: SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
setFormError(null);
setIsSubmitting(true);

const formData = new FormData(event.currentTarget);
const email = String(formData.get('email') ?? '');
const emailValue = formData.get('email');
const email = typeof emailValue === 'string' ? emailValue : '';

try {
const { error } = await authClient.requestPasswordReset({
email,
});

if (error) {
setFormError(error.message);
setFormError(error.message ?? null);
return;
}

Expand All @@ -46,10 +49,7 @@ export function SendResetEmail() {
return (
<form className="mt-8 space-y-4" onSubmit={handleResetRequest}>
<div>
<Label
htmlFor="email"
className="text-sm font-medium text-foreground"
>
<Label htmlFor="email" className="text-sm font-medium text-foreground">
Email
</Label>
<Input
Expand Down
13 changes: 8 additions & 5 deletions apps/web/src/app/(auth)/signup/signup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useState } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';

import type { FormEvent } from 'react';
import type { SyntheticEvent } from 'react';

import { IconBrandGithub, IconBrandGoogleFilled } from '@tabler/icons-react';

Expand Down Expand Up @@ -33,15 +33,18 @@ export function Signup() {

const displayError = formError ?? socialError;

const handleSignup = async (event: FormEvent<HTMLFormElement>) => {
const handleSignup = async (event: SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
setFormError(null);
setIsSubmitting(true);

const formData = new FormData(event.currentTarget);
const name = String(formData.get('name') ?? '');
const email = String(formData.get('email') ?? '');
const password = String(formData.get('password') ?? '');
const nameValue = formData.get('name');
const emailValue = formData.get('email');
const passwordValue = formData.get('password');
const name = typeof nameValue === 'string' ? nameValue : '';
const email = typeof emailValue === 'string' ? emailValue : '';
const password = typeof passwordValue === 'string' ? passwordValue : '';

try {
const { error } = await signUp.email({
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/(auth)/verify-email/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default async function VerifyEmailPage({
}) {
const session = await getSession();
const resolvedSearchParams = await searchParams;
const tokenParam = resolvedSearchParams?.token;
const tokenParam = resolvedSearchParams.token;
const token = Array.isArray(tokenParam) ? tokenParam[0] : tokenParam;

if (!session && !token) {
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/(landing)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Image from 'next/image';

import { Code, ListPlus, MousePointer, Server } from 'lucide-react';
import { Code, ListPlus, MousePointer } from 'lucide-react';

const githubUrl = 'https://github.com/eight-labs/formbase';

Expand Down
10 changes: 7 additions & 3 deletions apps/web/src/app/(main)/_components/user-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const UserDropdown = ({ className }: { className?: string }) => {
variant="ghost"
className={`h-auto p-0 hover:bg-transparent ${className ?? ''}`}
>
<UserAvatar src={user.image ?? null} seed={user.email ?? user.id} />
<UserAvatar src={user.image ?? null} seed={user.email} />
<ChevronDownIcon
aria-hidden="true"
className="opacity-60"
Expand All @@ -78,7 +78,7 @@ export const UserDropdown = ({ className }: { className?: string }) => {
<DropdownMenuGroup>
<DropdownMenuLabel className="flex min-w-0 flex-col">
<span className="truncate text-sm font-medium text-foreground">
{user.name ?? 'User'}
{user.name}
</span>
<span className="truncate text-xs font-normal text-muted-foreground">
{user.email}
Expand Down Expand Up @@ -155,7 +155,11 @@ export const UserDropdown = ({ className }: { className?: string }) => {
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuSeparator />
<SignoutMenuItem onClick={() => setSignoutDialogOpen(true)} />
<SignoutMenuItem
onClick={() => {
setSignoutDialogOpen(true);
}}
/>
</DropdownMenuContent>
</DropdownMenu>
<SignoutDialog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Link from 'next/link';
import { usePathname } from 'next/navigation';

import { GearIcon } from '@radix-ui/react-icons';
import { FileTextIcon } from 'lucide-react';
import { BookOpenIcon, FileTextIcon } from 'lucide-react';

import { cn } from '@formbase/ui/utils/cn';

Expand Down
6 changes: 4 additions & 2 deletions apps/web/src/app/(main)/dashboard/_components/form-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ export function FormCard({
<Button
variant="ghost"
className="h-8 w-8 p-0"
onClick={(e) => e.preventDefault()}
onClick={(e) => {
e.preventDefault();
}}
>
<span className="sr-only">Open Form Endpoint menu</span>
<DotsVerticalIcon className="h-4 w-4" />
Expand All @@ -118,7 +120,7 @@ export function FormCard({
<DropdownMenuItem
onClick={(e) => {
e.preventDefault();
handleDuplicate();
void handleDuplicate();
}}
disabled={isDuplicating}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import {
PopoverContent,
PopoverTrigger,
} from '@formbase/ui/primitives/popover';

import { cn } from '@formbase/ui/utils/cn';

import { CopyButton } from '~/components/copy-button';
Expand Down Expand Up @@ -79,7 +78,7 @@ export function ApiKeysSection() {
setNewKeyValue(data.key);
setCreateDialogOpen(false);
form.reset();
utils.apiKeys.list.invalidate();
void utils.apiKeys.list.invalidate();
toast.success('API key created');
},
});
Expand All @@ -88,7 +87,7 @@ export function ApiKeysSection() {
api.apiKeys.delete.useMutation({
onSuccess: () => {
setDeleteKeyId(null);
utils.apiKeys.list.invalidate();
void utils.apiKeys.list.invalidate();
toast.success('API key deleted');
},
});
Expand Down Expand Up @@ -180,7 +179,6 @@ export function ApiKeysSection() {
selected={field.value}
onSelect={field.onChange}
disabled={(date) => date < new Date()}
initialFocus
/>
</PopoverContent>
</Popover>
Expand All @@ -205,7 +203,9 @@ export function ApiKeysSection() {
<ApiKeyRow
key={apiKey.id}
apiKey={apiKey}
onDelete={() => setDeleteKeyId(apiKey.id)}
onDelete={() => {
setDeleteKeyId(apiKey.id);
}}
/>
))}
</div>
Expand All @@ -218,7 +218,12 @@ export function ApiKeysSection() {
</div>
)}

<Dialog open={!!newKeyValue} onOpenChange={() => setNewKeyValue(null)}>
<Dialog
open={!!newKeyValue}
onOpenChange={() => {
setNewKeyValue(null);
}}
>
<DialogContent showCloseButton={false}>
<DialogHeader>
<DialogTitle>API Key Created</DialogTitle>
Expand All @@ -231,14 +236,24 @@ export function ApiKeysSection() {
{newKeyValue && <CopyButton text={newKeyValue} />}
</div>
<DialogFooter>
<Button onClick={() => setNewKeyValue(null)}>Done</Button>
<Button
onClick={() => {
setNewKeyValue(null);
}}
>
Done
</Button>
</DialogFooter>
</DialogContent>
</Dialog>

<AlertDialog
open={!!deleteKeyId}
onOpenChange={(open) => !open && setDeleteKeyId(null)}
onOpenChange={(open) => {
if (!open) {
setDeleteKeyId(null);
}
}}
>
<AlertDialogContent>
<AlertDialogHeader>
Expand Down Expand Up @@ -278,7 +293,9 @@ interface ApiKeyRowProps {

function ApiKeyRow({ apiKey, onDelete }: ApiKeyRowProps) {
const isExpired = apiKey.expiresAt && new Date(apiKey.expiresAt) < new Date();
const { data: usageStats } = api.apiKeys.getUsageStats.useQuery({ id: apiKey.id });
const { data: usageStats } = api.apiKeys.getUsageStats.useQuery({
id: apiKey.id,
});

return (
<div className="flex items-center justify-between p-4">
Expand All @@ -295,7 +312,9 @@ function ApiKeyRow({ apiKey, onDelete }: ApiKeyRowProps) {
<code className="rounded bg-muted px-1.5 py-0.5">
{apiKey.keyPrefix}...
</code>
<span>Created {format(new Date(apiKey.createdAt), 'MMM d, yyyy')}</span>
<span>
Created {format(new Date(apiKey.createdAt), 'MMM d, yyyy')}
</span>
{apiKey.lastUsedAt && (
<span>
Last used {format(new Date(apiKey.lastUsedAt), 'MMM d, yyyy')}
Expand Down
7 changes: 4 additions & 3 deletions apps/web/src/app/(main)/dashboard/settings/profile-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import { toast } from 'sonner';
import { z } from 'zod';

import { type User } from '@formbase/auth';

import { LoadingButton } from '~/components/loading-button';
import {
Form,
FormControl,
Expand All @@ -21,6 +19,7 @@ import {
} from '@formbase/ui/primitives/form';
import { Input } from '@formbase/ui/primitives/input';

import { LoadingButton } from '~/components/loading-button';
import { api } from '~/lib/trpc/react';

const profileFormSchema = z.object({
Expand All @@ -34,8 +33,10 @@ const profileFormSchema = z.object({

type ProfileFormValues = z.infer<typeof profileFormSchema>;

type ProfileFormUser = Omit<User, 'name'> & { name: string | null };

type ProfileFormProps = {
user: User;
user: ProfileFormUser;
};

export function ProfileForm({ user }: ProfileFormProps) {
Expand Down
Loading
Loading