Incremental progress

This commit is contained in:
Ryan Pandya 2024-11-14 23:52:59 -08:00
parent 53ca8614b8
commit 0a0b697e6d
8 changed files with 597 additions and 19 deletions

View File

@ -32,7 +32,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { TRPCClientError } from "@trpc/client"; import { TRPCClientError } from "@trpc/client";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod"; import { z } from "zod";
import { HexColorPicker } from "react-colorful";
import { zLabelSchema } from "@lifetracker/shared/types/labels"; import { zLabelSchema } from "@lifetracker/shared/types/labels";
type CreateLabelSchema = z.infer<typeof zLabelSchema>; type CreateLabelSchema = z.infer<typeof zLabelSchema>;
@ -47,12 +47,12 @@ export default function AddLabelDialog({
const form = useForm<CreateLabelSchema>({ const form = useForm<CreateLabelSchema>({
resolver: zodResolver(zLabelSchema), resolver: zodResolver(zLabelSchema),
defaultValues: { defaultValues: {
code: -1, id: "69",
name: "", name: "Fuckdicks",
description: "", code: 420,
color: "#000022", description: "This shit sucks",
color: "#004400",
}, },
}); });
const { mutate, isPending } = api.labels.createLabel.useMutation({ const { mutate, isPending } = api.labels.createLabel.useMutation({
onSuccess: () => { onSuccess: () => {
@ -70,7 +70,7 @@ export default function AddLabelDialog({
} else { } else {
toast({ toast({
variant: "destructive", variant: "destructive",
description: "Failed to create user", description: "Failed to create label",
}); });
} }
}, },
@ -87,15 +87,11 @@ export default function AddLabelDialog({
<DialogTrigger asChild>{children}</DialogTrigger> <DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent> <DialogContent>
<DialogHeader> <DialogHeader>
<DialogTitle>New Label</DialogTitle> <DialogTitle>Add User</DialogTitle>
</DialogHeader> </DialogHeader>
<Form {...form}> <Form {...form}>
<form onSubmit={form.handleSubmit((data) => mutate(data))}> <form onSubmit={form.handleSubmit((val) => mutate(val))}>
<div className="flex w-full flex-col space-y-2"> <div className="flex w-full flex-col space-y-2">
<div className="flex">
</div>
<FormField <FormField
control={form.control} control={form.control}
name="name" name="name"
@ -114,7 +110,24 @@ export default function AddLabelDialog({
</FormItem> </FormItem>
)} )}
/> />
<FormField
control={form.control}
name="code"
render={({ field }) => (
<FormItem>
<FormLabel>Code</FormLabel>
<FormControl>
<Input
type="number"
placeholder="Code"
{...field}
className="w-full rounded border p-2"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField <FormField
control={form.control} control={form.control}
name="description" name="description"
@ -133,6 +146,24 @@ export default function AddLabelDialog({
</FormItem> </FormItem>
)} )}
/> />
<FormField
control={form.control}
name="color"
render={({ field }) => (
<FormItem>
<FormLabel>Color, hope you like hex codes</FormLabel>
<FormControl>
<Input
type="text"
placeholder="Color"
{...field}
className="w-full rounded border p-2"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter className="sm:justify-end"> <DialogFooter className="sm:justify-end">
<DialogClose asChild> <DialogClose asChild>
<Button type="button" variant="secondary"> <Button type="button" variant="secondary">
@ -151,6 +182,6 @@ export default function AddLabelDialog({
</form> </form>
</Form> </Form>
</DialogContent> </DialogContent>
</Dialog > </Dialog>
); );
} }

View File

@ -20,6 +20,7 @@ import AddLabelDialog from "./AddLabelDialog";
export default function LabelsView() { export default function LabelsView() {
const { data: session } = useSession(); const { data: session } = useSession();
const { data: labels } = api.labels.list.useQuery(); const { data: labels } = api.labels.list.useQuery();
const { data: labelStats } = api.labels.labelStats.useQuery();
const LabelsTable = ({ labels }) => ( const LabelsTable = ({ labels }) => (
<Table> <Table>
@ -32,7 +33,7 @@ export default function LabelsView() {
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{labels.labels.map((l) => ( {labels.labels.map((l) => (
<TableRow key={l.id}> <TableRow key={l.id} >
<TableCell className="py-1">{l.code}</TableCell> <TableCell className="py-1">{l.code}</TableCell>
<TableCell className="py-1">{l.name}</TableCell> <TableCell className="py-1">{l.name}</TableCell>
<TableCell className="py-1">{l.description}</TableCell> <TableCell className="py-1">{l.description}</TableCell>
@ -48,19 +49,19 @@ export default function LabelsView() {
> >
<Trash size={16} color="red" /> <Trash size={16} color="red" />
</ActionButtonWithTooltip> </ActionButtonWithTooltip>
<EditLabelDialog labelId={l.id} > <AddLabelDialog labelId={l.id} >
<ButtonWithTooltip <ButtonWithTooltip
tooltip="Edit" tooltip="Edit"
variant="outline" variant="outline"
> >
<Pencil size={16} color="red" /> <Pencil size={16} color="red" />
</ButtonWithTooltip> </ButtonWithTooltip>
</EditLabelDialog> </AddLabelDialog>
</TableCell> </TableCell>
</TableRow> </TableRow>
))} ))}
</TableBody> </TableBody>
</Table> </Table >
); );
return ( return (

View File

@ -0,0 +1 @@
ALTER TABLE `label` ADD `code` integer NOT NULL;

View File

@ -0,0 +1,505 @@
{
"version": "6",
"dialect": "sqlite",
"id": "d5294e8b-976b-4c92-bc82-b4e35e2683bb",
"prevId": "22c67302-ebcd-4ad9-8393-feea41c17455",
"tables": {
"account": {
"name": "account",
"columns": {
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"provider": {
"name": "provider",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"providerAccountId": {
"name": "providerAccountId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"token_type": {
"name": "token_type",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"scope": {
"name": "scope",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"session_state": {
"name": "session_state",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"account_userId_user_id_fk": {
"name": "account_userId_user_id_fk",
"tableFrom": "account",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"account_provider_providerAccountId_pk": {
"columns": [
"provider",
"providerAccountId"
],
"name": "account_provider_providerAccountId_pk"
}
},
"uniqueConstraints": {}
},
"apiKey": {
"name": "apiKey",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"createdAt": {
"name": "createdAt",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"keyId": {
"name": "keyId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"keyHash": {
"name": "keyHash",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"apiKey_keyId_unique": {
"name": "apiKey_keyId_unique",
"columns": [
"keyId"
],
"isUnique": true
},
"apiKey_name_userId_unique": {
"name": "apiKey_name_userId_unique",
"columns": [
"name",
"userId"
],
"isUnique": true
}
},
"foreignKeys": {
"apiKey_userId_user_id_fk": {
"name": "apiKey_userId_user_id_fk",
"tableFrom": "apiKey",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"config": {
"name": "config",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"day": {
"name": "day",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"mood": {
"name": "mood",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"date": {
"name": "date",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"day_date_unique": {
"name": "day_date_unique",
"columns": [
"date"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"label": {
"name": "label",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"createdAt": {
"name": "createdAt",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"code": {
"name": "code",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"color": {
"name": "color",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "'#000000'"
},
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"label_userId_name_unique": {
"name": "label_userId_name_unique",
"columns": [
"userId",
"name"
],
"isUnique": true
}
},
"foreignKeys": {
"label_userId_user_id_fk": {
"name": "label_userId_user_id_fk",
"tableFrom": "label",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"session": {
"name": "session",
"columns": {
"sessionToken": {
"name": "sessionToken",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"expires": {
"name": "expires",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"session_userId_user_id_fk": {
"name": "session_userId_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"user": {
"name": "user",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"emailVerified": {
"name": "emailVerified",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"role": {
"name": "role",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "'user'"
}
},
"indexes": {
"user_email_unique": {
"name": "user_email_unique",
"columns": [
"email"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"verificationToken": {
"name": "verificationToken",
"columns": {
"identifier": {
"name": "identifier",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"expires": {
"name": "expires",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"verificationToken_identifier_token_pk": {
"columns": [
"identifier",
"token"
],
"name": "verificationToken_identifier_token_pk"
}
},
"uniqueConstraints": {}
}
},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@ -50,6 +50,13 @@
"when": 1731649046343, "when": 1731649046343,
"tag": "0006_milky_hellion", "tag": "0006_milky_hellion",
"breakpoints": true "breakpoints": true
},
{
"idx": 7,
"version": "6",
"when": 1731656341890,
"tag": "0007_unusual_terror",
"breakpoints": true
} }
] ]
} }

View File

@ -114,6 +114,7 @@ export const labels = sqliteTable(
.$defaultFn(() => createId()), .$defaultFn(() => createId()),
createdAt: createdAtField(), createdAt: createdAtField(),
name: text("name").notNull(), name: text("name").notNull(),
code: integer("code").notNull(),
description: text("description"), description: text("description"),
color: text("color").default("#000000"), color: text("color").default("#000000"),
userId: text("userId") userId: text("userId")

View File

@ -12,6 +12,8 @@ export type ZLabels = z.infer<typeof zLabelSchema>;
export const zGetLabelResponseSchema = z.object({ export const zGetLabelResponseSchema = z.object({
id: z.string(), id: z.string(),
code: z.number(), code: z.number(),
color: z.string(),
description: z.string().optional(),
name: z.string(), name: z.string(),
numEntries: z.number(), numEntries: z.number(),
}); });

View File

@ -20,6 +20,9 @@ async function createLabel(
input: z.infer<typeof zLabelSchema>, input: z.infer<typeof zLabelSchema>,
ctx: Context, ctx: Context,
) { ) {
console.log("Creating a label");
return ctx.db.transaction(async (trx) => { return ctx.db.transaction(async (trx) => {
try { try {
@ -58,6 +61,31 @@ async function createLabel(
} }
export const labelsAppRouter = router({ export const labelsAppRouter = router({
labelStats: authedProcedure
.output(
z.record(
z.string(),
z.object({
numEntries: z.number(),
}),
),
)
.query(async ({ ctx }) => {
const [labelIds] = await Promise.all([
ctx.db.select({ id: labels.id }).from(labels)
]);
const results: Record<
string,
{ numEntries: number }
> = {};
for (const label of labelIds) {
results[label.id] = {
numEntries: 3330,
};
}
return results;
}),
list: authedProcedure list: authedProcedure
.output( .output(
z.object({ z.object({
@ -69,6 +97,7 @@ export const labelsAppRouter = router({
.select({ .select({
id: labels.id, id: labels.id,
name: labels.name, name: labels.name,
code: labels.code,
color: labels.color, color: labels.color,
description: labels.description, description: labels.description,
}) })
@ -79,6 +108,7 @@ export const labelsAppRouter = router({
labels: res.map((r) => ({ labels: res.map((r) => ({
id: r.id, id: r.id,
name: r.name, name: r.name,
code: r.code,
color: r.color, color: r.color,
description: r.description, description: r.description,
numEntries: 420, numEntries: 420,