Skip to content

Commit

Permalink
feat: new sign up UI
Browse files Browse the repository at this point in the history
  • Loading branch information
BlankParticle committed Jul 19, 2024
1 parent 2393f6a commit cbcbef9
Show file tree
Hide file tree
Showing 29 changed files with 1,505 additions and 1,172 deletions.
2 changes: 1 addition & 1 deletion apps/platform/trpc/routers/authRouter/passkeyRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const passkeyRouter = router({
username: zodSchemas.username()
})
)
.query(async ({ input, ctx }) => {
.mutation(async ({ input, ctx }) => {
const { db } = ctx;
const { username } = input;
const { available, error } = await validateUsername(db, input.username);
Expand Down
44 changes: 44 additions & 0 deletions apps/platform/trpc/routers/authRouter/passwordRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,50 @@ import { ms } from '@u22n/utils/ms';
import { ratelimiter } from '~platform/trpc/ratelimit';

export const passwordRouter = router({
signUpWithPassword: publicProcedure
.unstable_concat(turnstileProcedure)
.use(ratelimiter({ limit: 10, namespace: 'signUp.password' }))
.input(
z.object({
username: zodSchemas.username(),
password: strongPasswordSchema
})
)
.mutation(async ({ ctx, input }) => {
const { password, username } = input;
const { db, event } = ctx;

const { accountId, publicId } = await db.transaction(async (tx) => {
const { available, error } = await validateUsername(tx, username);
if (!available) {
throw new TRPCError({
code: 'FORBIDDEN',
message: `Username Error : ${error}`
});
}
const passwordHash = await new Argon2id().hash(password);
const publicId = typeIdGenerator('account');

const newUser = await tx.insert(accounts).values({
username,
publicId,
passwordHash
});

return {
accountId: Number(newUser.insertId),
publicId
};
});

await createLuciaSessionCookie(event, {
accountId,
username,
publicId
});

return { success: true };
}),
signUpWithPassword2FA: publicProcedure
.unstable_concat(turnstileProcedure)
.use(ratelimiter({ limit: 10, namespace: 'signUp.password' }))
Expand Down
4 changes: 1 addition & 3 deletions apps/platform/trpc/routers/authRouter/signupRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ export const signupRouter = router({
username: zodSchemas.username()
})
)
.query(async ({ ctx, input }) => {
return await validateUsername(ctx.db, input.username);
}),
.query(({ ctx, input }) => validateUsername(ctx.db, input.username)),
checkPasswordStrength: publicProcedure
.use(ratelimiter({ limit: 50, namespace: 'check.password' }))
.input(
Expand Down
44 changes: 42 additions & 2 deletions apps/platform/trpc/routers/orgRouter/orgCrudRouter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { z } from 'zod';
import { router, accountProcedure } from '~platform/trpc/trpc';
import type { DBType } from '@u22n/database';
import { eq, and } from '@u22n/database/orm';
import { eq, and, like } from '@u22n/database/orm';
import {
orgs,
orgMembers,
Expand Down Expand Up @@ -56,7 +56,7 @@ export const crudRouter = router({
.string()
.min(5)
.max(64)
.regex(/^[a-z0-9]*$/, {
.regex(/^[a-z0-9\-]*$/, {
message: 'Only lowercase letters and numbers'
})
})
Expand All @@ -65,6 +65,46 @@ export const crudRouter = router({
return await validateOrgShortcode(ctx.db, input.shortcode);
}),

generateOrgShortcode: accountProcedure
.input(
z.object({
orgName: z.string().min(5)
})
)
.query(async ({ ctx, input }) => {
const autoShortcode = input.orgName
.toLowerCase()
.replace(/[^a-z0-9\-]/g, '');
const existingOrgs = await ctx.db.query.orgs.findMany({
where: like(orgs.shortcode, `${autoShortcode}%`),
columns: {
shortcode: true
}
});

if (existingOrgs.length === 0) {
return { shortcode: autoShortcode.substring(0, 32) };
}
const existingShortcodeList = existingOrgs.map((org) => org.shortcode);
let currentSuffix = existingShortcodeList.length;
let retries = 0;
let newShortcode = `${autoShortcode.substring(0, 28)}-${currentSuffix}`;

while (existingShortcodeList.includes(newShortcode)) {
currentSuffix++;
newShortcode = `${autoShortcode.substring(0, 28)}-${currentSuffix}`;
retries++;
if (retries > 30) {
throw new TRPCError({
code: 'CONFLICT',
message:
'Failed to generate unique shortcode, please type one manually'
});
}
}
return { shortcode: newShortcode };
}),

createNewOrg: accountProcedure
.input(
z.object({
Expand Down
15 changes: 7 additions & 8 deletions apps/platform/trpc/routers/userRouter/profileRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,23 +116,22 @@ export const profileRouter = router({
.input(
z.object({
profilePublicId: typeIdValidator('orgMemberProfile'),
fName: z.string(),
lName: z.string(),
title: z.string(),
blurb: z.string(),
imageId: z.string().uuid().optional().nullable(),
handle: z.string().min(2).max(20)
name: z.string(),
title: z.string().optional(),
blurb: z.string().optional(),
handle: z.string().min(2).max(20).optional()
})
)
.mutation(async ({ ctx, input }) => {
const { db, account } = ctx;
const accountId = account.id;
const [firstName, ...lastName] = input.name.split(' ');

await db
.update(orgMemberProfiles)
.set({
firstName: input.fName,
lastName: input.lName,
firstName,
lastName: lastName.join(' '),
title: input.title,
blurb: input.blurb,
handle: input.handle
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/app/(login)/_components/passkey-login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export function PasskeyLoginButton() {
description: 'Redirecting you to create an organization'
});
router.push('/join/org');
return;
}

toast.success('Sign in successful!', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ export default function Page() {
const { loading: saveLoading, run: saveProfile } = useLoading(async () => {
if (!initData) return;
await updateProfileApi.mutateAsync({
fName: firstNameValue,
lName: lastNameValue,
name: `${firstNameValue} ${lastNameValue}`,
blurb: bioValue,
title: titleValue,
handle: initData.profile.handle ?? '',
Expand Down
22 changes: 16 additions & 6 deletions apps/web/src/app/join/_components/stepper.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Separator } from '@/src/components/shadcn-ui/separator';
import { cn } from '@/src/lib/utils';
import { Check } from '@phosphor-icons/react';

export default function Stepper({
step,
Expand All @@ -9,15 +9,25 @@ export default function Stepper({
total: number;
}) {
return (
<div className="mx-auto flex w-full max-w-96 items-center justify-center gap-2">
<div className="flex gap-1">
<span className="sr-only">{`This is step ${step} of ${total}`}</span>
{Array.from({ length: total }).map((_, i) => (
<Separator
<div
key={i}
className={cn(
'my-4 h-2 flex-1 rounded-md',
i < step ? 'bg-grass-6' : 'bg-gray-6'
'text-base-11 bg-base-1 border-base-7 flex h-5 w-5 select-none items-center justify-center rounded-full border text-center text-xs font-semibold',
step === i + 1 && 'bg-accent-9 border-none text-white',
step > i + 1 && 'bg-green-9 border-none text-white'
)}>
{step > i + 1 ? (
<Check
size={12}
weight="bold"
/>
) : (
i + 1
)}
/>
</div>
))}
</div>
);
Expand Down
8 changes: 2 additions & 6 deletions apps/web/src/app/join/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@

export default function Page({ children }: { children: React.ReactNode }) {
return (
<div className="flex h-full w-full flex-col items-center justify-center">
<div className="w-full text-center">
<h1 className="font-display text-2xl">Let&apos;s Make your</h1>
<h2 className="font-display text-5xl">UnInbox</h2>
{children}
</div>
<div className="bg-base-2 flex h-full w-full flex-col items-center justify-center">
{children}
</div>
);
}
Loading

0 comments on commit cbcbef9

Please sign in to comment.