Skip to content

Commit

Permalink
feat: Add fields support (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
evadecker authored Sep 27, 2024
1 parent e93f7cc commit b57e265
Show file tree
Hide file tree
Showing 18 changed files with 254 additions and 169 deletions.
5 changes: 5 additions & 0 deletions .changeset/odd-needles-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"namesake": patch
---

Make header sticky, add backend support for defining fields within a quest
8 changes: 4 additions & 4 deletions convex/_generated/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import type * as http from "../http.js";
import type * as questSteps from "../questSteps.js";
import type * as quests from "../quests.js";
import type * as seed from "../seed.js";
import type * as types from "../types.js";
import type * as userQuests from "../userQuests.js";
import type * as users from "../users.js";
import type * as usersQuests from "../usersQuests.js";
import type * as validators from "../validators.js";

/**
* A utility for referencing Convex functions in your app's API.
Expand All @@ -44,9 +44,9 @@ declare const fullApi: ApiFromModules<{
questSteps: typeof questSteps;
quests: typeof quests;
seed: typeof seed;
types: typeof types;
userQuests: typeof userQuests;
users: typeof users;
usersQuests: typeof usersQuests;
validators: typeof validators;
}>;
export declare const api: FilterApi<
typeof fullApi,
Expand Down
173 changes: 118 additions & 55 deletions convex/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
type RemixiconComponentType,
RiAccountCircleLine,
RiAppleFill,
RiAtLine,
RiAuctionLine,
RiAwardLine,
RiBankCardLine,
Expand All @@ -10,15 +11,18 @@ import {
RiBlueskyFill,
RiBuildingLine,
RiCakeLine,
RiCalendarLine,
RiCapsuleLine,
RiCarLine,
RiChat1Line,
RiCheckboxLine,
RiChromeFill,
RiCodeLine,
RiCommunityLine,
RiContactsBookLine,
RiDiscordFill,
RiDropboxFill,
RiDropdownList,
RiFacebookCircleFill,
RiFileLine,
RiFlowerLine,
Expand All @@ -29,11 +33,13 @@ import {
RiGovernmentLine,
RiGraduationCapLine,
RiHandHeartLine,
RiHashtag,
RiHeartLine,
RiHomeLine,
RiHospitalLine,
RiIdCardLine,
RiImageLine,
RiInputField,
RiInstagramFill,
RiKeyLine,
RiLightbulbLine,
Expand All @@ -44,6 +50,7 @@ import {
RiMentalHealthLine,
RiMusic2Line,
RiNewsLine,
RiParagraph,
RiPatreonFill,
RiPhoneLine,
RiPinterestFill,
Expand Down Expand Up @@ -167,60 +174,116 @@ export const ICONS: Record<string, RemixiconComponentType> = {
whatsapp: RiWhatsappFill,
windows: RiWindowsFill,
youtube: RiYoutubeFill,
};
} as const;
export type Icon = keyof typeof ICONS;

export enum JURISDICTIONS {
AK = "Alaska",
AL = "Alabama",
AR = "Arkansas",
AZ = "Arizona",
CA = "California",
CO = "Colorado",
CT = "Connecticut",
DC = "District of Columbia",
DE = "Delaware",
FED = "Federal",
FL = "Florida",
GA = "Georgia",
HI = "Hawaii",
IA = "Iowa",
ID = "Idaho",
IL = "Illinois",
IN = "Indiana",
KS = "Kansas",
KY = "Kentucky",
LA = "Louisiana",
MA = "Massachusetts",
MD = "Maryland",
ME = "Maine",
MI = "Michigan",
MN = "Minnesota",
MO = "Missouri",
MS = "Mississippi",
MT = "Montana",
NC = "North Carolina",
ND = "North Dakota",
NE = "Nebraska",
NH = "New Hampshire",
NJ = "New Jersey",
NM = "New Mexico",
NV = "Nevada",
NY = "New York",
OH = "Ohio",
OK = "Oklahoma",
OR = "Oregon",
PA = "Pennsylvania",
PR = "Puerto Rico",
RI = "Rhode Island",
SC = "South Carolina",
SD = "South Dakota",
TN = "Tennessee",
TX = "Texas",
UT = "Utah",
VA = "Virginia",
VT = "Vermont",
WA = "Washington",
WI = "Wisconsin",
WV = "West Virginia",
WY = "Wyoming",
export const JURISDICTIONS = {
AK: "Alaska",
AL: "Alabama",
AR: "Arkansas",
AZ: "Arizona",
CA: "California",
CO: "Colorado",
CT: "Connecticut",
DC: "District of Columbia",
DE: "Delaware",
FED: "Federal",
FL: "Florida",
GA: "Georgia",
HI: "Hawaii",
IA: "Iowa",
ID: "Idaho",
IL: "Illinois",
IN: "Indiana",
KS: "Kansas",
KY: "Kentucky",
LA: "Louisiana",
MA: "Massachusetts",
MD: "Maryland",
ME: "Maine",
MI: "Michigan",
MN: "Minnesota",
MO: "Missouri",
MS: "Mississippi",
MT: "Montana",
NC: "North Carolina",
ND: "North Dakota",
NE: "Nebraska",
NH: "New Hampshire",
NJ: "New Jersey",
NM: "New Mexico",
NV: "Nevada",
NY: "New York",
OH: "Ohio",
OK: "Oklahoma",
OR: "Oregon",
PA: "Pennsylvania",
PR: "Puerto Rico",
RI: "Rhode Island",
SC: "South Carolina",
SD: "South Dakota",
TN: "Tennessee",
TX: "Texas",
UT: "Utah",
VA: "Virginia",
VT: "Vermont",
WA: "Washington",
WI: "Wisconsin",
WV: "West Virginia",
WY: "Wyoming",
} as const;
export type Jurisdiction = keyof typeof JURISDICTIONS;

interface FieldDetails {
label: string;
icon: RemixiconComponentType;
}
export const FIELDS: Record<string, FieldDetails> = {
text: {
label: "Text",
icon: RiInputField,
},
textarea: {
label: "Textarea",
icon: RiParagraph,
},
date: {
label: "Date",
icon: RiCalendarLine,
},
select: {
label: "Select",
icon: RiDropdownList,
},
checkbox: {
label: "Checkbox",
icon: RiCheckboxLine,
},
number: {
label: "Number",
icon: RiHashtag,
},
email: {
label: "Email",
icon: RiAtLine,
},
phone: {
label: "Phone",
icon: RiPhoneLine,
},
} as const;
export type Field = keyof typeof FIELDS;

export const THEMES = {
system: "System",
light: "Light",
dark: "Dark",
} as const;
export type Theme = keyof typeof THEMES;

export const ROLES = {
user: "User",
editor: "Editor",
admin: "Admin",
} as const;
export type Role = keyof typeof ROLES;
2 changes: 1 addition & 1 deletion convex/forms.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { v } from "convex/values";
import { mutation, query } from "./_generated/server";
import { userMutation } from "./helpers";
import { jurisdiction } from "./types";
import { jurisdiction } from "./validators";

// TODO: Add `returns` value validation
// https://docs.convex.dev/functions/validation
Expand Down
4 changes: 2 additions & 2 deletions convex/quests.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { v } from "convex/values";
import { query } from "./_generated/server";
import { userMutation } from "./helpers";
import { icon, jurisdiction } from "./types";
import { icon, jurisdiction } from "./validators";

// TODO: Add `returns` value validation
// https://docs.convex.dev/functions/validation
Expand Down Expand Up @@ -65,7 +65,7 @@ export const permanentlyDeleteQuest = userMutation({
handler: async (ctx, args) => {
// Delete userQuests
const userQuests = await ctx.db
.query("usersQuests")
.query("userQuests")
.withIndex("questId", (q) => q.eq("questId", args.questId))
.collect();
for (const userQuest of userQuests) await ctx.db.delete(userQuest._id);
Expand Down
52 changes: 4 additions & 48 deletions convex/schema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { authTables } from "@convex-dev/auth/server";
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
import { icon, jurisdiction, role, theme } from "./types";
import { field, icon, jurisdiction, role, theme } from "./validators";

/**
* Represents a PDF form that can be filled out by users.
Expand Down Expand Up @@ -38,12 +38,6 @@ const quests = defineTable({
steps: v.optional(v.array(v.id("questSteps"))),
});

const sharedFieldProps = {
label: v.string(),
helpText: v.optional(v.string()),
isRequired: v.boolean(),
};

/**
* Represents a single step in a quest.
* @param title - The title of the step. (e.g. "Fill out form")
Expand All @@ -55,45 +49,7 @@ const questSteps = defineTable({
creationUser: v.id("users"),
title: v.string(),
description: v.optional(v.string()),
fields: v.optional(
v.array(
v.union(
v.object({
...sharedFieldProps,
type: v.literal("text"),
}),
v.object({
...sharedFieldProps,
type: v.literal("textarea"),
}),
v.object({
...sharedFieldProps,
type: v.literal("date"),
}),
v.object({
...sharedFieldProps,
type: v.literal("select"),
options: v.array(v.string()),
}),
v.object({
...sharedFieldProps,
type: v.literal("checkbox"),
}),
v.object({
...sharedFieldProps,
type: v.literal("number"),
}),
v.object({
...sharedFieldProps,
type: v.literal("email"),
}),
v.object({
...sharedFieldProps,
type: v.literal("phone"),
}),
),
),
),
fields: v.optional(v.array(field)),
}).index("questId", ["questId"]);

/**
Expand Down Expand Up @@ -124,7 +80,7 @@ const users = defineTable({
* @param questId
* @param completionTime - Time in ms since epoch when the user marked the quest as complete.
*/
const usersQuests = defineTable({
const userQuests = defineTable({
userId: v.id("users"),
questId: v.id("quests"),
completionTime: v.optional(v.number()),
Expand All @@ -138,5 +94,5 @@ export default defineSchema({
quests,
questSteps,
users,
usersQuests,
userQuests,
});
26 changes: 0 additions & 26 deletions convex/types.ts

This file was deleted.

Loading

0 comments on commit b57e265

Please sign in to comment.