Skip to content

Commit

Permalink
Feat/unique team name (#190)
Browse files Browse the repository at this point in the history
* CHORE/todos added

* FEAT/form schema added

* FEAT/teams schema

* FEAT/router
  • Loading branch information
AugustinSorel authored Jun 30, 2024
1 parent 2ea75b6 commit ce78bc1
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 17 deletions.
22 changes: 21 additions & 1 deletion src/app/_components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ const FeatureRequest = () => {

const CreateTeamDialog = () => {
const [isDialogOpen, setIsDialogOpen] = useState(false);
const formSchema = teamSchema.pick({ name: true });
const formSchema = useFormSchema();
const utils = api.useUtils();
const router = useRouter();

Expand Down Expand Up @@ -717,3 +717,23 @@ const CreateTeamDialog = () => {
</Dialog>
);
};

const useFormSchema = () => {
const utils = api.useUtils();

return teamSchema.pick({ name: true }).refine(
(data) => {
const teams = utils.team.all.getData();

return !teams?.find(
(team) => team.team.name.toLowerCase() === data.name.toLowerCase(),
);
},
(data) => {
return {
message: `${data.name} is already used`,
path: ["name"],
};
},
);
};
2 changes: 2 additions & 0 deletions src/server/api/routers/exercise.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const exerciseRouter = createTRPCRouter({
return exerciseCreated;
});
} catch (e) {
//TODO: use pgError fn
const error = e as object;

if ("code" in error && error.code === "23505") {
Expand Down Expand Up @@ -71,6 +72,7 @@ export const exerciseRouter = createTRPCRouter({
} catch (e) {
const error = e as object;

//TODO: use pgError fn
if ("code" in error && error.code === "23505") {
throw new TRPCError({
code: "CONFLICT",
Expand Down
2 changes: 2 additions & 0 deletions src/server/api/routers/exerciseData.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const exerciseDataRouter = createTRPCRouter({
} catch (e) {
const error = e as object;

//TODO: use pgError fn
if ("code" in error && error.code === "23505") {
throw new TRPCError({
code: "CONFLICT",
Expand Down Expand Up @@ -83,6 +84,7 @@ export const exerciseDataRouter = createTRPCRouter({
} catch (e) {
const error = e as object;

//TODO: use pgError fn
if ("code" in error && error.code === "23505") {
throw new TRPCError({
code: "CONFLICT",
Expand Down
30 changes: 23 additions & 7 deletions src/server/api/routers/team.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,34 @@ import { sendInviteToTeamEmail } from "@/lib/email";
import { and, eq } from "drizzle-orm";
import { teamInviteSchema } from "@/schemas/teamInvite.schema";
import { z } from "zod";
import { isPgError } from "@/server/db/utils";

export const teamRouter = createTRPCRouter({
create: protectedProcedure
.input(teamSchema.pick({ name: true }))
.mutation(async ({ ctx, input }) => {
const [team] = await ctx.db
.insert(teams)
.values({
name: input.name,
authorId: ctx.session.user.id,
})
.returning();
let team = null;

try {
const res = await ctx.db
.insert(teams)
.values({
name: input.name,
authorId: ctx.session.user.id,
})
.returning();

team = res.at(0);
} catch (e) {
if (isPgError(e) && e.code === "23505") {
throw new TRPCError({
code: "CONFLICT",
message: `${input.name} is already used`,
});
}

throw new TRPCError({ code: "INTERNAL_SERVER_ERROR" });
}

if (!team) {
throw new TRPCError({
Expand Down
24 changes: 15 additions & 9 deletions src/server/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,21 @@ export const exercisesData = pgTable(
}),
);

export const teams = pgTable("team", {
id: uuid("id").defaultRandom().primaryKey(),
name: text("name").notNull(),
authorId: text("member_id")
.references(() => users.id, { onDelete: "cascade" })
.notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
export const teams = pgTable(
"team",
{
id: uuid("id").defaultRandom().primaryKey(),
name: text("name").notNull(),
authorId: text("member_id")
.references(() => users.id, { onDelete: "cascade" })
.notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
},
(table) => ({
unq: unique().on(table.authorId, table.name),
}),
);

export const usersToTeams = pgTable(
"users_to_teams",
Expand Down

0 comments on commit ce78bc1

Please sign in to comment.