Skip to content

Commit 6d553dc

Browse files
fix: use debounce while generating shortcode based on org name (#605)
1 parent 8463eb3 commit 6d553dc

File tree

2 files changed

+48
-38
lines changed

2 files changed

+48
-38
lines changed

apps/platform/trpc/routers/orgRouter/orgCrudRouter.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export const crudRouter = router({
5656
.string()
5757
.min(5)
5858
.max(64)
59-
.regex(/^[a-z0-9\-]*$/, {
59+
.regex(/^[a-z0-9]*$/, {
6060
message: 'Only lowercase letters and numbers'
6161
})
6262
})
@@ -74,25 +74,28 @@ export const crudRouter = router({
7474
.query(async ({ ctx, input }) => {
7575
const autoShortcode = input.orgName
7676
.toLowerCase()
77-
.replace(/[^a-z0-9\-]/g, '');
77+
.replace(/[^a-z0-9]/g, '');
7878
const existingOrgs = await ctx.db.query.orgs.findMany({
7979
where: like(orgs.shortcode, `${autoShortcode}%`),
8080
columns: {
8181
shortcode: true
8282
}
8383
});
8484

85-
if (existingOrgs.length === 0) {
85+
const existingShortcodeList = existingOrgs.map((org) => org.shortcode);
86+
if (
87+
existingShortcodeList.length === 0 ||
88+
!existingShortcodeList.includes(autoShortcode)
89+
) {
8690
return { shortcode: autoShortcode.substring(0, 32) };
8791
}
88-
const existingShortcodeList = existingOrgs.map((org) => org.shortcode);
8992
let currentSuffix = existingShortcodeList.length;
9093
let retries = 0;
91-
let newShortcode = `${autoShortcode.substring(0, 28)}-${currentSuffix}`;
94+
let newShortcode = `${autoShortcode.substring(0, 28)}${currentSuffix}`;
9295

9396
while (existingShortcodeList.includes(newShortcode)) {
9497
currentSuffix++;
95-
newShortcode = `${autoShortcode.substring(0, 28)}-${currentSuffix}`;
98+
newShortcode = `${autoShortcode.substring(0, 28)}${currentSuffix}`;
9699
retries++;
97100
if (retries > 30) {
98101
throw new TRPCError({

apps/web/src/app/join/org/_components/create-org.tsx

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { platform } from '@/src/lib/trpc';
44
import { Button } from '@/src/components/shadcn-ui/button';
55
import { IdentificationCard } from '@phosphor-icons/react';
6-
import { useMemo, useState } from 'react';
6+
import { useEffect, useMemo, useState } from 'react';
77
import { z } from 'zod';
88
import { useRouter } from 'next/navigation';
99
import { toast } from 'sonner';
@@ -16,19 +16,21 @@ import {
1616
TooltipContent,
1717
TooltipTrigger
1818
} from '@/src/components/shadcn-ui/tooltip';
19+
import { useDebounce } from '@uidotdev/usehooks';
1920

2021
export function CreateOrg() {
2122
const [orgName, setOrgName] = useState('');
2223
const [orgShortcode, setOrgShortcode] = useState('');
2324
const [customShortcode, setCustomShortcode] = useState(false);
2425
const router = useRouter();
26+
const debouncedOrgName = useDebounce(orgName, 750);
2527

2628
const [shortcodeValid, shortcodeError] = useMemo(() => {
2729
const { success, error } = z
2830
.string()
2931
.min(5)
3032
.max(64)
31-
.regex(/^[a-z0-9\-]*$/, {
33+
.regex(/^[a-z0-9]*$/, {
3234
message: 'Only lowercase letters and numbers'
3335
})
3436
.safeParse(orgShortcode);
@@ -48,16 +50,48 @@ export function CreateOrg() {
4850
}
4951
);
5052

51-
const { refetch: generateShortcode } =
53+
const { data: generateShortcodeData, error: generateShortcodeError } =
5254
platform.org.crud.generateOrgShortcode.useQuery(
5355
{
54-
orgName
56+
orgName: debouncedOrgName
5557
},
5658
{
57-
enabled: false
59+
enabled: !customShortcode && debouncedOrgName.trim().length >= 5
5860
}
5961
);
6062

63+
const generateOrgShortcodeUtils =
64+
platform.useUtils().org.crud.generateOrgShortcode;
65+
66+
// Update the shortcode if the org name changes
67+
useEffect(() => {
68+
if (generateShortcodeData) setOrgShortcode(generateShortcodeData.shortcode);
69+
}, [generateShortcodeData]);
70+
71+
// If org name is less than 5 characters, clear the shortcode as min length is 5
72+
useEffect(() => {
73+
if (debouncedOrgName.trim().length < 5 && !customShortcode) {
74+
void generateOrgShortcodeUtils.invalidate();
75+
setOrgShortcode('');
76+
}
77+
}, [
78+
debouncedOrgName,
79+
customShortcode,
80+
orgShortcode,
81+
generateOrgShortcodeUtils
82+
]);
83+
84+
// handle shortcode generation error
85+
useEffect(() => {
86+
if (generateShortcodeError) {
87+
toast.error('An Error Occurred while generating the Org Shortcode', {
88+
description: generateShortcodeError.message
89+
});
90+
setOrgShortcode(debouncedOrgName.toLowerCase().replace(/[^a-z0-9]/g, ''));
91+
setCustomShortcode(true);
92+
}
93+
}, [debouncedOrgName, generateShortcodeError]);
94+
6195
const { mutateAsync: createOrg, isPending } =
6296
platform.org.crud.createNewOrg.useMutation({
6397
onError: (e) => {
@@ -74,33 +108,6 @@ export function CreateOrg() {
74108
fullWidth
75109
inputSize="lg"
76110
value={orgName}
77-
onBlur={async () => {
78-
// If the org name is empty, clear the shortcode
79-
if (orgName.trim().length === 0 && !customShortcode) {
80-
if (orgShortcode) {
81-
setOrgShortcode('');
82-
}
83-
}
84-
// If the org name is less than 5 characters, do not generate a shortcode
85-
if (customShortcode || orgName.trim().length < 5) return;
86-
const { data, error } = await generateShortcode();
87-
88-
if (error) {
89-
toast.error(
90-
'An Error Occurred while generating the Org Shortcode',
91-
{
92-
description: error.message
93-
}
94-
);
95-
setOrgShortcode(orgName.toLowerCase().replace(/[^a-z0-9]/g, ''));
96-
setCustomShortcode(true);
97-
return;
98-
}
99-
100-
if (data) {
101-
setOrgShortcode(data.shortcode);
102-
}
103-
}}
104111
onChange={(e) => setOrgName(e.target.value)}
105112
leadingSlot={IdentificationCard}
106113
/>

0 commit comments

Comments
 (0)