Skip to content

Commit

Permalink
feat: Support selecting a birthplace outside the US (#358)
Browse files Browse the repository at this point in the history
  • Loading branch information
evadecker authored Jan 31, 2025
1 parent 31d6e04 commit 6b25e40
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/old-eggs-compete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"namesake": patch
---

Support selecting a birthplace outside the US
6 changes: 6 additions & 0 deletions convex/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ export const JURISDICTIONS = {
} as const;
export type Jurisdiction = keyof typeof JURISDICTIONS;

export const BIRTHPLACES = {
...JURISDICTIONS,
other: "I was born outside the US",
};
export type Birthplace = keyof typeof BIRTHPLACES;

/**
* Fields for input forms.
*/
Expand Down
5 changes: 3 additions & 2 deletions convex/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { authTables } from "@convex-dev/auth/server";
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
import {
birthplace,
category,
jurisdiction,
role,
Expand Down Expand Up @@ -134,8 +135,8 @@ const users = defineTable({
emailVerified: v.optional(v.boolean()),
/** The US State where the user resides. */
residence: v.optional(jurisdiction),
/** The US State where the user was born. */
birthplace: v.optional(jurisdiction),
/** The US State where the user was born, or "other" if they were born outside the US. */
birthplace: v.optional(birthplace),
/** Whether the user is a minor. */
isMinor: v.optional(v.boolean()),
}).index("email", ["email"]);
Expand Down
4 changes: 2 additions & 2 deletions convex/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { query } from "./_generated/server";
import type { Role } from "./constants";
import { DUPLICATE_EMAIL, INVALID_EMAIL } from "./errors";
import { userMutation } from "./helpers";
import { jurisdiction } from "./validators";
import { birthplace, jurisdiction } from "./validators";

export const getAll = query({
args: {},
Expand Down Expand Up @@ -91,7 +91,7 @@ export const setResidence = userMutation({
});

export const setBirthplace = userMutation({
args: { birthplace: jurisdiction },
args: { birthplace: birthplace },
handler: async (ctx, args) => {
await ctx.db.patch(ctx.userId, { birthplace: args.birthplace });
},
Expand Down
5 changes: 5 additions & 0 deletions convex/validators.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { v } from "convex/values";
import {
BIRTHPLACES,
CATEGORIES,
JURISDICTIONS,
ROLES,
Expand All @@ -12,6 +13,10 @@ export const jurisdiction = v.union(
...Object.keys(JURISDICTIONS).map((jurisdiction) => v.literal(jurisdiction)),
);

export const birthplace = v.union(
...Object.keys(BIRTHPLACES).map((birthplace) => v.literal(birthplace)),
);

export const status = v.union(
...Object.keys(STATUS).map((status) => v.literal(status)),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "@/components/common";
import { api } from "@convex/_generated/api";
import {
BIRTHPLACES,
CATEGORIES,
JURISDICTIONS,
type Jurisdiction,
Expand Down Expand Up @@ -67,9 +68,16 @@ export const JurisdictionInterstitial = ({
});
} else {
navigate({ to: "/" });
toast.error(
"Namesake doesn't support that state yet. Please check back soon.",
);

if (type === "birthCertificate" && selection === "other") {
toast.info(
"Namesake can only assist with birth certificates for US states.",
);
} else {
toast.info(
"Namesake doesn't support that state yet. Please check back soon.",
);
}
}
} catch (err) {
setError("Failed to update. Please try again.");
Expand Down Expand Up @@ -118,7 +126,9 @@ export const JurisdictionInterstitial = ({
className="flex-1 max-h-[60dvh]"
aria-label="Select a state"
>
{Object.entries(JURISDICTIONS).map(([value, label]) => (
{Object.entries(
type === "birthCertificate" ? BIRTHPLACES : JURISDICTIONS,
).map(([value, label]) => (
<ListBoxItem key={value} id={value}>
{label}
</ListBoxItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Banner, Button, Form, Select, SelectItem } from "@/components/common";
import { SettingsItem } from "@/components/settings";
import { api } from "@convex/_generated/api";
import type { Doc } from "@convex/_generated/dataModel";
import { JURISDICTIONS, type Jurisdiction } from "@convex/constants";
import { BIRTHPLACES, type Birthplace } from "@convex/constants";
import { useMutation } from "convex/react";
import { useEffect, useState } from "react";
import { toast } from "sonner";
Expand All @@ -13,8 +13,8 @@ type EditBirthplaceSettingProps = {

export const EditBirthplaceSetting = ({ user }: EditBirthplaceSettingProps) => {
const [isEditing, setIsEditing] = useState(false);
const [birthplace, setBirthplace] = useState<Jurisdiction>(
user.birthplace as Jurisdiction,
const [birthplace, setBirthplace] = useState<Birthplace>(
user.birthplace as Birthplace,
);
const [error, setError] = useState<string>();
const [isSubmitting, setIsSubmitting] = useState(false);
Expand All @@ -27,7 +27,7 @@ export const EditBirthplaceSetting = ({ user }: EditBirthplaceSettingProps) => {
}, [birthplace, user.birthplace]);

const handleCancel = () => {
setBirthplace(user.birthplace as Jurisdiction);
setBirthplace(user.birthplace as Birthplace);
setIsEditing(false);
};

Expand Down Expand Up @@ -63,14 +63,14 @@ export const EditBirthplaceSetting = ({ user }: EditBirthplaceSettingProps) => {
name="birthplace"
selectedKey={birthplace}
onSelectionChange={(key) => {
setBirthplace(key as Jurisdiction);
setBirthplace(key as Birthplace);
setError(undefined);
}}
isRequired
placeholder="Select state"
isDisabled={isSubmitting}
>
{Object.entries(JURISDICTIONS).map(([value, label]) => (
{Object.entries(BIRTHPLACES).map(([value, label]) => (
<SelectItem key={value} id={value}>
{label}
</SelectItem>
Expand Down
8 changes: 8 additions & 0 deletions src/routes/_authenticated/_home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const Route = createFileRoute("/_authenticated/_home")({

function IndexRoute() {
const MyQuests = () => {
const user = useQuery(api.users.getCurrent);
const userQuests = useQuery(api.userQuests.count) ?? 0;
const completedQuests = useQuery(api.userQuests.countCompleted) ?? 0;
const questsByCategory = useQuery(api.userQuests.getByCategory);
Expand Down Expand Up @@ -86,6 +87,13 @@ function IndexRoute() {
const userQuest = questsByCategory?.[category]?.[0];
const config = CORE_CATEGORIES[category];

if (
category === "birthCertificate" &&
user?.birthplace === "other"
) {
return null;
}

if (userQuest) {
return (
<NavItem
Expand Down

0 comments on commit 6b25e40

Please sign in to comment.