Skip to content

Commit cdc0a44

Browse files
minor ui cleanup
1 parent a2b38cd commit cdc0a44

5 files changed

Lines changed: 25 additions & 67 deletions

File tree

demos/react-convex-todolist/convex/lists.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ export const create = mutation({
3030
* Update a list given a partial list record data.
3131
*/
3232
export const update = mutation({
33-
args: schema.tables.todos.validator,
33+
// The uuid is required, every other field is an optional patch
34+
args: v.object({ uuid: v.string() }).extend(schema.tables.lists.validator.partial().fields),
3435
handler: async ({ db }, { uuid, ...fields }) => {
3536
const matching = await findListByUuid({ db, uuid });
3637
if (!matching) {

demos/react-convex-todolist/convex/schema.ts

Lines changed: 8 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ export default defineSchema({
1818
})
1919
),
2020

21-
// External stable key from PowerSync writes.
22-
uuid: v.string(),
23-
// Legacy fields kept for backwards compatibility with existing data.
24-
owner: v.optional(v.string()),
25-
archived: v.optional(v.number())
21+
/**
22+
* Due to ID mapping, we cant require a strict Convex `id` ID field - which
23+
* correlates to a matching todo record here.
24+
* This value will be the local-first UUID.
25+
*/
26+
uuid: v.string()
2627
}).index('by_uuid', ['uuid']),
2728

2829
todos: defineTable({
29-
// Basic fields
3030
/**
3131
* Due to ID mapping, we cant require a strict Convex `id` ID field - which
3232
* correlates to a matching todo record here.
@@ -40,59 +40,10 @@ export default defineSchema({
4040
/**
4141
* Local-first version of list_id
4242
*/
43-
list_uuid: v.string(),
44-
45-
// All Convex datatypes for stress testing
46-
// String types
47-
title: v.optional(v.string()),
48-
notes: v.optional(v.string()),
49-
category: v.optional(v.string()),
50-
51-
// Number types
52-
priority: v.optional(v.number()),
53-
estimated_hours: v.optional(v.float64()),
54-
progress_percentage: v.optional(v.float64()),
55-
56-
// Boolean types
57-
is_urgent: v.optional(v.boolean()),
58-
is_private: v.optional(v.boolean()),
59-
has_attachments: v.optional(v.boolean()),
60-
61-
// Array types
62-
tags: v.optional(v.array(v.string())),
63-
dependencies: v.optional(v.array(v.id('todos'))),
64-
assigned_users: v.optional(v.array(v.string())),
65-
66-
// Object types
67-
metadata: v.optional(v.record(v.string(), v.any())),
68-
custom_fields: v.optional(v.record(v.string(), v.union(v.string(), v.number(), v.boolean()))),
69-
70-
// ID references
71-
parent_task_id: v.optional(v.id('todos')),
72-
project_id: v.optional(v.id('lists')),
73-
74-
// Union types
75-
status: v.optional(
76-
v.union(v.literal('pending'), v.literal('in_progress'), v.literal('completed'), v.literal('cancelled'))
77-
),
78-
difficulty: v.optional(v.union(v.literal('easy'), v.literal('medium'), v.literal('hard'))),
79-
80-
// Null handling
81-
archived_at: v.optional(v.union(v.null(), v.string())),
82-
deleted_by: v.optional(v.union(v.null(), v.string())),
83-
84-
// Legacy fields kept for backwards compatibility
85-
completed: v.optional(v.number()),
86-
created_by: v.optional(v.union(v.null(), v.string())),
87-
completed_by: v.optional(v.union(v.null(), v.string())),
88-
photo_id: v.optional(v.union(v.null(), v.string())),
89-
owner_id: v.optional(v.string())
43+
list_uuid: v.string()
9044
})
9145
.index('by_uuid', ['uuid'])
92-
.index('by_list_id', ['list_id'])
93-
.index('by_status', ['status'])
94-
.index('by_priority', ['priority'])
95-
.index('by_project', ['project_id']),
46+
.index('by_list_id', ['list_id']),
9647

9748
powersync_checkpoints: defineTable({
9849
last_updated: v.float64()

demos/react-convex-todolist/convex/todos.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ export const create = mutation({
4343
* Update a todo record given a partial update.
4444
*/
4545
export const update = mutation({
46-
args: schema.tables.todos.validator,
46+
// The uuid is required, every other field is an optional patch
47+
args: v.object({ uuid: v.string() }).extend(schema.tables.todos.validator.partial().fields),
4748
handler: async ({ db }, { uuid, ...fields }) => {
4849
let matching = await findTodoByUuid({ db, uuid });
4950
if (!matching) {

demos/react-convex-todolist/src/components/widgets/OutlinedComposer.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import { alpha } from '@mui/material/styles';
44
import type { SxProps, Theme } from '@mui/material/styles';
55
import React from 'react';
66

7+
export type OutlinedComposerSubmitSource = 'enter' | 'button' | 'submit';
8+
79
export type OutlinedComposerProps = {
810
value: string;
911
onChange: (value: string) => void;
10-
onSubmit: () => void | Promise<void>;
12+
onSubmit: (source?: OutlinedComposerSubmitSource) => void | Promise<void>;
1113
placeholder: string;
1214
inputAriaLabel: string;
1315
submitAriaLabel: string;
@@ -35,7 +37,7 @@ export function OutlinedComposer(props: OutlinedComposerProps) {
3537

3638
const handleSubmit = (event?: React.FormEvent) => {
3739
event?.preventDefault();
38-
void onSubmit();
40+
void onSubmit('submit');
3941
};
4042

4143
return (
@@ -58,11 +60,11 @@ export function OutlinedComposer(props: OutlinedComposerProps) {
5860
onKeyDown: (e) => {
5961
if (multiline && e.key === 'Enter' && !e.shiftKey) {
6062
e.preventDefault();
61-
void onSubmit();
63+
void onSubmit('enter');
6264
}
6365
if (!multiline && e.key === 'Enter') {
6466
e.preventDefault();
65-
void onSubmit();
67+
void onSubmit('enter');
6668
}
6769
}
6870
}}
@@ -103,9 +105,10 @@ export function OutlinedComposer(props: OutlinedComposerProps) {
103105
})}
104106
/>
105107
<IconButton
106-
type="submit"
108+
type="button"
107109
color="secondary"
108110
aria-label={submitAriaLabel}
111+
onClick={() => void onSubmit('button')}
109112
sx={(theme) => ({
110113
alignSelf: 'stretch',
111114
flexShrink: 0,

demos/react-convex-todolist/src/components/widgets/TodoListsWidget.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { usePowerSync, useQuery } from '@powersync/react';
66
import { useMemo, useState } from 'react';
77
import { useNavigate, useParams } from 'react-router-dom';
88
import { ListItemWidget } from './ListItemWidget';
9-
import { OutlinedComposer } from './OutlinedComposer';
9+
import { OutlinedComposer, OutlinedComposerSubmitSource } from './OutlinedComposer';
1010

1111
export type TodoListsWidgetProps = {
1212
selectedId?: string;
@@ -98,7 +98,7 @@ export function TodoListsWidget(props: TodoListsWidgetProps) {
9898
});
9999
};
100100

101-
const createNewList = async () => {
101+
const createNewList = async (source?: OutlinedComposerSubmitSource) => {
102102
const name = newListName.trim();
103103
if (!name) {
104104
setNewListName('');
@@ -118,7 +118,9 @@ export function TodoListsWidget(props: TodoListsWidgetProps) {
118118
throw new Error('Could not create list');
119119
}
120120
setNewListName('');
121-
navigate(`${TODO_LISTS_ROUTE}/${created.id}`);
121+
if (source === 'button' || source === 'submit') {
122+
navigate(`${TODO_LISTS_ROUTE}/${created.id}`);
123+
}
122124
};
123125

124126
return (

0 commit comments

Comments
 (0)