@maestro-js/agent-skills 1.0.0-alpha.2 → 1.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +19 -0
- package/package.json +8 -7
- package/{dist → skills}/choosing-an-npm-package/SKILL.md +5 -4
- package/skills/iconify/SKILL.md +82 -0
- package/skills/iconify/scripts/iconify.js +111 -0
- package/skills/iso-fns/SKILL.md +137 -0
- package/skills/iso-fns/references/api_reference.md +435 -0
- package/skills/maestro-architecture/SKILL.md +552 -0
- package/skills/maestro-examples/SKILL.md +140 -0
- package/skills/maestro-examples/references/cadence/cadence-web/.auth/user.json +15 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/app.css +112 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/auth-layout.tsx +39 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/back-link.tsx +24 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/button-group.tsx +78 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/button-link.tsx +77 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/button.tsx +139 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/checkbox.tsx +210 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/chip.tsx +161 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/container.tsx +85 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/date-range.tsx +141 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/date-time-picker.tsx +199 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/empty-state.tsx +19 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/form-page.tsx +41 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/form.tsx +106 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/animated-popover.tsx +27 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/button-context.ts +13 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/calendar-month-year-picker.tsx +283 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/form-field.tsx +231 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/get-button-classes.ts +141 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/headless-button.tsx +39 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/icon.tsx +29 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/inline-alert.tsx +57 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/interaction-form.tsx +87 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/menu.tsx +189 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/optional-link.tsx +18 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/page-header.tsx +19 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/rich-text-editor.tsx +352 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/select.tsx +219 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/spinner.tsx +19 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/headless-templated-row-table.ts +553 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/index.tsx +44 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/server-table.ts +146 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-actions.tsx +79 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-container.tsx +176 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-container.type-test.ts +158 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-filters/date-range-filter.tsx +230 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-filters/select-filter.tsx +214 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-filters/sort.tsx +88 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-primitives.tsx +229 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-toolbar.tsx +303 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-types.ts +64 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/use-client-table.ts +160 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/use-client-table.type-test.ts +220 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/use-server-table.ts +195 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/use-server-table.type-test.ts +177 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/tag-editor.tsx +53 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/tag-field.tsx +253 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/text-field.tsx +147 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/toast.tsx +182 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/top-nav.tsx +175 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/entry.client.tsx +21 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/entry.server.tsx +13 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/csrf-middleware.server.ts +17 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/custom-error-status-code-middleware.server.ts +31 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/rate-limiting-middleware.server.ts +36 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/redirect-with-toast.server.ts +14 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/request-context.server.ts +40 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/security-headers-middleware.server.ts +10 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/icons/types.ts +36 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/root.tsx +208 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/_index.tsx +5 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/activity.tsx +124 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/archive.tsx +187 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/auth.forgot-password.tsx +108 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/auth.login.tsx +132 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/auth.logout.tsx +17 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/auth.register.tsx +172 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/auth.reset-password.tsx +137 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/contacts.$id.edit.tsx +89 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/contacts.$id.tsx +521 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/contacts.new.tsx +56 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/contacts.tsx +183 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/settings.tsx +158 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/users.tsx +263 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes.ts +4 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/services.server.ts +1 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/colors.ts +47 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/compose-event-handlers.ts +13 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/compose-refs.ts +35 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/format-date.ts +10 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/overridable-component-helper.ts +31 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/sanitize-html.ts +16 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/tw.ts +16 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-hydrated.ts +12 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-prevent-default.ts +30 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-query-state.ts +629 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-render-props.ts +42 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-spin-delay.ts +27 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-stable-accessor.ts +14 -0
- package/skills/maestro-examples/references/cadence/cadence-web/instrument.server.mjs +29 -0
- package/skills/maestro-examples/references/cadence/cadence-web/package.json +60 -0
- package/skills/maestro-examples/references/cadence/cadence-web/playwright.config.ts +39 -0
- package/skills/maestro-examples/references/cadence/cadence-web/react-router.config.ts +12 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tailwind.config.ts +7 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/activity/filter-activity.spec.ts +93 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/activity/recent-activity.spec.ts +70 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/archive/archive-view.spec.ts +62 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth/login-invalid.spec.ts +68 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth/login-valid.spec.ts +45 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth/logout.spec.ts +46 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth/password-reset.spec.ts +105 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth/register.spec.ts +39 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth.setup.ts +48 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/authorization/member-ownership.spec.ts +104 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/authorization/viewer-read-only.spec.ts +103 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/constants.ts +11 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/archive-restore.spec.ts +77 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/create-contact.spec.ts +56 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/delete-contact.spec.ts +53 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/edit-contact.spec.ts +60 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/filter-by-last-contacted.spec.ts +85 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/filter-by-tag.spec.ts +68 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/global-search.spec.ts +57 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/sort-contacts.spec.ts +60 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/tags.spec.ts +85 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/view-detail.spec.ts +58 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/interactions/delete-interaction.spec.ts +59 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/interactions/edit-interaction.spec.ts +68 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/interactions/log-email.spec.ts +57 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/interactions/log-note.spec.ts +56 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/interactions/rich-text-formatting.spec.ts +97 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/organization/delete.spec.ts +70 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/organization/edit-name.spec.ts +51 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/users/change-role.spec.ts +62 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/users/invite-user.spec.ts +56 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/users/remove-user.spec.ts +58 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tsconfig.json +22 -0
- package/skills/maestro-examples/references/cadence/cadence-web/vite.config.ts +37 -0
- package/skills/maestro-examples/references/cadence/config/agent-container.ts +4 -0
- package/skills/maestro-examples/references/cadence/config/cadence-web.ts +12 -0
- package/skills/maestro-examples/references/cadence/config/db-migrate.ts +9 -0
- package/skills/maestro-examples/references/cadence/config/queue-processor.ts +11 -0
- package/skills/maestro-examples/references/cadence/config/services.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000001_organizations-and-users.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000002_contacts.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000003_interactions.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000004_remember-me-tokens.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000005_password-reset-tokens.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000006_queue-and-recurring-jobs.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000001_organizations-and-users-down.sql +2 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000001_organizations-and-users-up.sql +24 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000002_contacts-down.sql +1 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000002_contacts-up.sql +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000003_interactions-down.sql +1 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000003_interactions-up.sql +15 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000004_remember-me-tokens-down.sql +1 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000004_remember-me-tokens-up.sql +12 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000005_password-reset-tokens-down.sql +1 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000005_password-reset-tokens-up.sql +11 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000006_queue-and-recurring-jobs-down.sql +2 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000006_queue-and-recurring-jobs-up.sql +21 -0
- package/skills/maestro-examples/references/cadence/package.json +17 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/package.json +17 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/src/contact/index.ts +57 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/src/index.ts +4 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/src/interaction/index.ts +45 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/src/organization/index.ts +32 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/src/user/index.ts +69 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/tsconfig.json +9 -0
- package/skills/maestro-examples/references/cadence/packages/services/package.json +43 -0
- package/skills/maestro-examples/references/cadence/packages/services/run-tests.ts +59 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/auth/auth-db-provider.ts +202 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/auth/auth-use-cases.ts +155 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/auth/index.ts +17 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/auth/profile-db-provider.ts +17 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/contact/contact-db-provider.test.ts +120 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/contact/contact-db-provider.ts +145 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/contact/contact-use-cases.ts +196 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/contact/index.ts +29 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/index.ts +23 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/interaction/index.ts +25 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/interaction/interaction-db-provider.test.ts +128 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/interaction/interaction-db-provider.ts +98 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/interaction/interaction-use-cases.ts +171 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/maestro.ts +218 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/organization/index.ts +8 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/organization/organization-db-provider.test.ts +53 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/organization/organization-db-provider.ts +60 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/organization/organization-use-cases.ts +88 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/permissions.ts +28 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/contact-seed.ts +30 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/index.ts +13 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/interaction-seed.ts +29 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/organization-seed.ts +25 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/seed-pipe.ts +38 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/user-seed.ts +27 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/user/index.ts +27 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/user/user-db-provider.test.ts +100 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/user/user-db-provider.ts +69 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/user/user-use-cases.ts +162 -0
- package/skills/maestro-examples/references/cadence/packages/services/tsconfig.json +9 -0
- package/skills/maestro-examples/references/cadence/scripts/foreign-key-delete-behavior.ts +106 -0
- package/skills/maestro-examples/references/cadence/specs/app.md +72 -0
- package/skills/maestro-examples/references/cadence/specs/data-models.md +80 -0
- package/skills/maestro-examples/references/cadence/specs/multi-tenant-security.md +239 -0
- package/skills/maestro-examples/references/cadence/specs/rich-text-editor.md +108 -0
- package/skills/maestro-examples/references/cadence/specs/table.md +151 -0
- package/skills/maestro-examples/references/cadence/specs/use-cases.md +62 -0
- package/skills/maestro-examples/references/cadence/tsconfig.json +29 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/app.css +152 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/alert-dialog.tsx +153 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/avatar.tsx +57 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/button-group.tsx +78 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/button-link.tsx +77 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/button.tsx +139 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/channel-card.tsx +40 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/checkbox-group.tsx +175 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/checkbox.tsx +210 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/chip.tsx +161 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/container.tsx +85 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/date-picker.tsx +214 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/date-time-picker.tsx +199 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/dialog.tsx +114 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/enum-chip.tsx +33 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/file-input.tsx +248 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/form.tsx +106 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/headless-file-input.tsx +365 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/animated-popover.tsx +27 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/button-context.ts +13 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/calendar-month-year-picker.tsx +283 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/form-field.tsx +231 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/get-button-classes.ts +141 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/headless-button.tsx +39 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/pdf-dist.client.ts +9 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/icon.tsx +29 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/image-grid.tsx +96 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/image-input.tsx +268 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/inline-alert.tsx +57 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/like-button.tsx +48 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/menu.tsx +189 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/pdf-input.tsx +252 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/pdf.tsx +89 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/post-card.tsx +147 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/post-composer.tsx +166 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/radio-group.tsx +115 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/select.tsx +219 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/spinner.tsx +19 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/tag-field.tsx +253 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/text-area.tsx +151 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/text-field.tsx +147 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/toast.tsx +179 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/entry.client.tsx +21 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/entry.server.tsx +12 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/csrf-hidden-input.tsx +6 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/csrf-middleware.server.ts +17 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/custom-error-status-code-middleware.server.ts +18 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/rate-limiting-middleware.server.ts +36 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/redirect-with-toast.server.ts +14 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/request-context.server.ts +40 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/security-headers-middleware.server.ts +10 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/icons/types.ts +26 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/root.tsx +164 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_auth/forgot-password.tsx +90 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_auth/login.tsx +104 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_auth/logout.tsx +44 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_auth/reset-password.tsx +130 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_auth/signup.tsx +91 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_browse/_layout.tsx +36 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_browse/c.new.tsx +47 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_browse/index.tsx +3 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/api/hide-post.$postId.tsx +30 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/api/like.$postId.tsx +22 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug/_layout.tsx +108 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug/post.new.tsx +59 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug.edit.tsx +53 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug.manage/_layout.tsx +123 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug.manage/add-moderator.tsx +48 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug.manage/transfer-ownership.tsx +71 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug.post.$postId.tsx +119 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/files.$.tsx +22 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/health.tsx +3 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/settings.tsx +128 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes.ts +4 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/services.server.ts +1 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/colors.ts +47 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/compose-refs.ts +35 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/enum-colors.ts +4 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/file-input.ts +52 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/tw.ts +16 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-element-size.ts +35 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-number-input.ts +143 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-pagination.ts +41 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-prevent-default.ts +30 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-profile.ts +7 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-render-props.ts +42 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-spin-delay.ts +27 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-stable-accessor.ts +14 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-tab-indicator.ts +107 -0
- package/skills/maestro-examples/references/chorus/chorus-web/environment.d.ts +15 -0
- package/skills/maestro-examples/references/chorus/chorus-web/instrument.server.mjs +29 -0
- package/skills/maestro-examples/references/chorus/chorus-web/package.json +54 -0
- package/skills/maestro-examples/references/chorus/chorus-web/playwright.config.ts +39 -0
- package/skills/maestro-examples/references/chorus/chorus-web/react-router.config.ts +12 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/auth-landing.test.ts +8 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/auth-login.test.ts +40 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/auth-logout.test.ts +8 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/auth-signup.test.ts +15 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/auth.setup.ts +42 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-browse.test.ts +43 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-create.test.ts +34 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-edit.test.ts +33 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-manage-moderators.test.ts +59 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-manage-permissions.test.ts +55 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-transfer.test.ts +47 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/constants.ts +7 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/forgot-password.test.ts +33 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/hide-post-author.test.ts +62 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/hide-post-nonauthor.test.ts +36 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/like-toggle.test.ts +60 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/like-unauth.test.ts +37 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/post-create.test.ts +30 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/post-listing.test.ts +33 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/post-reply.test.ts +48 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/post-view-unauth.test.ts +37 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/settings-duplicate.test.ts +28 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/settings-update.test.ts +34 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/settings-view.test.ts +17 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/signup-validation.test.ts +51 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tsconfig.json +14 -0
- package/skills/maestro-examples/references/chorus/chorus-web/vite.config.ts +38 -0
- package/skills/maestro-examples/references/chorus/config/app-a.ts +7 -0
- package/skills/maestro-examples/references/chorus/config/chorus-web.ts +7 -0
- package/skills/maestro-examples/references/chorus/config/db-migrate.ts +9 -0
- package/skills/maestro-examples/references/chorus/config/queue-processor.ts +7 -0
- package/skills/maestro-examples/references/chorus/config/services.ts +15 -0
- package/skills/maestro-examples/references/chorus/infrastructure/cdk/index.ts +60 -0
- package/skills/maestro-examples/references/chorus/infrastructure/cdk.context.json +5 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260303005902_init_authentication.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260308234835_add-maestro-queue-table.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260315051819_channels.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260315052202_channel-moderators.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260315052539_posts.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260315052734_post-images.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260315053110_likes.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260303005902_init_authentication-down.sql +3 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260303005902_init_authentication-up.sql +40 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260308234835_add-maestro-queue-table-down.sql +3 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260308234835_add-maestro-queue-table-up.sql +23 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315051819_channels-down.sql +1 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315051819_channels-up.sql +11 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052202_channel-moderators-down.sql +1 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052202_channel-moderators-up.sql +7 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052539_posts-down.sql +1 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052539_posts-up.sql +14 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052734_post-images-down.sql +1 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052734_post-images-up.sql +7 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315053110_likes-down.sql +1 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315053110_likes-up.sql +8 -0
- package/skills/maestro-examples/references/chorus/infrastructure/package.json +20 -0
- package/skills/maestro-examples/references/chorus/infrastructure/tsconfig.json +8 -0
- package/skills/maestro-examples/references/chorus/package.json +17 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/other/generate-email-modules.ts +22 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/other/generate-email-previews.ts +18 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/package.json +27 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/components/button.tsx +19 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/components/root-container.tsx +29 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/components/tailwind-wrapper.tsx +113 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/email-modules.ts +9 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/emails/password-reset.tsx +41 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/index.ts +3 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/render-email-template.ts +24 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/utils/tw.ts +5 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/tsconfig.json +11 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/package.json +17 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/src/channel/index.ts +41 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/src/index.ts +4 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/src/like/index.ts +16 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/src/post/index.ts +44 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/src/profile/index.ts +80 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/tsconfig.json +9 -0
- package/skills/maestro-examples/references/chorus/packages/services/environment.d.ts +7 -0
- package/skills/maestro-examples/references/chorus/packages/services/package.json +47 -0
- package/skills/maestro-examples/references/chorus/packages/services/run-tests.ts +59 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/auth/auth-use-cases.ts +178 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/auth/authenticatable-db-provider.ts +59 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/auth/index.ts +29 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/auth/password-reset-token-db-provider.ts +58 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/auth/remember-me-token-db-provider.ts +82 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/channel/channel-db-provider.test.ts +85 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/channel/channel-db-provider.ts +158 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/channel/channel-use-cases.ts +303 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/channel/index.ts +29 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/index.ts +21 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/like/index.ts +6 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/like/like-db-provider.test.ts +47 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/like/like-db-provider.ts +53 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/like/like-use-cases.ts +31 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/maestro.ts +215 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/permissions.ts +16 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/post/index.ts +25 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/post/post-db-provider.test.ts +68 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/post/post-db-provider.ts +219 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/post/post-use-cases.ts +184 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/post/redact-hidden-post.ts +4 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/profile/index.ts +17 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/profile/profile-db-provider.test.ts +57 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/profile/profile-db-provider.ts +75 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/profile/profile-use-cases.ts +61 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/channel-seed.ts +27 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/index.ts +13 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/like-seed.ts +21 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/post-seed.ts +27 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/profile-seed.ts +28 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/seed-pipe.ts +38 -0
- package/skills/maestro-examples/references/chorus/packages/services/tsconfig.json +9 -0
- package/skills/maestro-examples/references/chorus/scripts/foreign-key-delete-behavior.ts +111 -0
- package/skills/maestro-examples/references/chorus/specs/app.md +73 -0
- package/skills/maestro-examples/references/chorus/specs/data-models.md +48 -0
- package/skills/maestro-examples/references/chorus/specs/database-schema.md +59 -0
- package/skills/maestro-examples/references/chorus/specs/use-cases.md +33 -0
- package/skills/maestro-examples/references/chorus/tsconfig.json +29 -0
- package/skills/maestro-examples/references/setlist/IMPLEMENTATION_PLAN.md +88 -0
- package/skills/maestro-examples/references/setlist/config/db-migrate.ts +9 -0
- package/skills/maestro-examples/references/setlist/config/queue-processor.ts +11 -0
- package/skills/maestro-examples/references/setlist/config/services.ts +16 -0
- package/skills/maestro-examples/references/setlist/config/setlist-web.ts +12 -0
- package/skills/maestro-examples/references/setlist/infrastructure/cdk/index.ts +56 -0
- package/skills/maestro-examples/references/setlist/infrastructure/cdk.context.json +5 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/20260316000000_init.ts +16 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/20260317000000_add-queue-and-recurring-job-tables.ts +22 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/sqls/20260316000000_init-down.sql +5 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/sqls/20260316000000_init-up.sql +68 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/sqls/20260317000000_add-queue-and-recurring-job-tables-down.sql +2 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/sqls/20260317000000_add-queue-and-recurring-job-tables-up.sql +21 -0
- package/skills/maestro-examples/references/setlist/infrastructure/package.json +20 -0
- package/skills/maestro-examples/references/setlist/infrastructure/tsconfig.json +8 -0
- package/skills/maestro-examples/references/setlist/package.json +19 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/other/generate-email-modules.ts +22 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/other/generate-email-previews.ts +18 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/package.json +27 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/components/button.tsx +19 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/components/root-container.tsx +29 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/components/tailwind-wrapper.tsx +113 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/email-modules.ts +9 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/emails/magic-link-login.tsx +49 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/index.ts +3 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/render-email-template.ts +24 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/utils/tw.ts +5 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/tsconfig.json +11 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/tsup.config.ts +10 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/package.json +21 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/area/index.ts +28 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/index.ts +6 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/magic-link/index.ts +20 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/position.ts +137 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/project/index.ts +44 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/task/index.ts +41 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/user/index.ts +28 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/tests/position.test.ts +106 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/tsconfig.json +9 -0
- package/skills/maestro-examples/references/setlist/packages/services/package.json +40 -0
- package/skills/maestro-examples/references/setlist/packages/services/run-tests.ts +59 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/area/area-db-provider.test.ts +29 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/area/area-db-provider.ts +81 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/area/area-use-cases.ts +130 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/area/index.ts +27 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/auth-db-provider.test.ts +34 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/auth-db-provider.ts +24 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/auth-use-cases.ts +110 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/index.ts +18 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/magic-link-db-provider.test.ts +52 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/magic-link-db-provider.ts +59 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/user-db-provider.test.ts +33 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/user-db-provider.ts +55 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/verify-magic-link-credentials.ts +39 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/index.ts +20 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/maestro.ts +175 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/project/index.ts +29 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/project/project-db-provider.test.ts +46 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/project/project-db-provider.ts +114 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/project/project-use-cases.ts +183 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/task/index.ts +39 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/task/task-db-provider.test.ts +53 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/task/task-db-provider.ts +219 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/task/task-use-cases.ts +303 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/area-seed.ts +25 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/index.ts +13 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/project-seed.ts +29 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/seed-pipe.ts +38 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/task-seed.ts +31 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/user-seed.ts +24 -0
- package/skills/maestro-examples/references/setlist/packages/services/tsconfig.json +9 -0
- package/skills/maestro-examples/references/setlist/queue-processor/package.json +17 -0
- package/skills/maestro-examples/references/setlist/queue-processor/src/index.ts +29 -0
- package/skills/maestro-examples/references/setlist/queue-processor/src/recurring-jobs.ts +13 -0
- package/skills/maestro-examples/references/setlist/queue-processor/tsconfig.json +4 -0
- package/skills/maestro-examples/references/setlist/scripts/foreign-key-delete-behavior.ts +107 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/app.css +158 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/alert-dialog.tsx +153 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/app-dnd-provider.tsx +180 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/area-form.tsx +113 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/button-group.tsx +78 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/button.tsx +139 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/checkbox.tsx +210 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/context-menu.tsx +78 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/date-picker.tsx +214 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/dnd-collision-detection.ts +28 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/dnd-utils.ts +11 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/drag-ghost.tsx +24 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/form.tsx +107 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/animated-popover.tsx +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/button-context.ts +13 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/calendar-month-year-picker.tsx +283 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/form-field.tsx +231 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/get-button-classes.ts +141 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/headless-button.tsx +39 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/icon.tsx +29 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/inline-alert.tsx +57 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/project-form.tsx +153 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/select.tsx +219 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/helpers.ts +73 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/index.ts +6 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/inline-inputs.tsx +128 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/sidebar.tsx +333 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/sortable-rows.tsx +256 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/use-sidebar-dnd.ts +261 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/spinner.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-inline-create.tsx +51 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/index.ts +3 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/task-date-helpers.ts +16 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/task-expanded-detail.tsx +273 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/task-keyboard-helpers.ts +5 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/task-list.tsx +134 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/task-row.tsx +100 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/types.ts +49 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/use-expanded-cache.ts +22 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/use-sticky-task.ts +24 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/use-task-reorder.ts +140 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/text-area.tsx +151 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/text-field.tsx +147 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/toast.tsx +179 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/entry.client.tsx +21 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/entry.server.tsx +13 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/csrf-middleware.server.ts +17 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/custom-error-status-code-middleware.server.ts +31 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/rate-limiting-middleware.server.ts +36 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/redirect-with-toast.server.ts +14 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/request-context.server.ts +52 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/security-headers-middleware.server.ts +10 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/hooks/use-area-actions.ts +44 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/hooks/use-csrf-token.ts +6 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/hooks/use-project-actions.ts +80 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/hooks/use-task-actions.ts +65 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/root.tsx +218 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/areas.$id.delete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/areas.$id.edit.tsx +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/areas.$id.reorder.tsx +30 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/areas.tsx +23 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.complete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.delete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.edit.tsx +32 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.move.tsx +23 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.reorder.tsx +30 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.uncomplete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.tsx +23 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.complete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.delete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.edit.tsx +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.move.tsx +30 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.reorder.tsx +32 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.uncomplete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.tsx +23 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/areas.$id.tsx +155 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/auth.login.tsx +98 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/auth.logout.tsx +17 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/auth.verify.tsx +154 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/completed.tsx +121 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/inbox.tsx +68 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/projects.$id.tsx +217 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/today.tsx +86 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/upcoming.tsx +83 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes.ts +4 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/services.server.ts +1 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/colors.ts +47 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/compose-refs.ts +35 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/tw.ts +16 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-dismiss.ts +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-fetcher-complete.ts +17 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-prevent-default.ts +30 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-render-props.ts +42 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-spin-delay.ts +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-stable-accessor.ts +14 -0
- package/skills/maestro-examples/references/setlist/setlist-web/environment.d.ts +8 -0
- package/skills/maestro-examples/references/setlist/setlist-web/instrument.server.mjs +29 -0
- package/skills/maestro-examples/references/setlist/setlist-web/knip.json +3 -0
- package/skills/maestro-examples/references/setlist/setlist-web/package.json +52 -0
- package/skills/maestro-examples/references/setlist/setlist-web/playwright.config.ts +39 -0
- package/skills/maestro-examples/references/setlist/setlist-web/react-router.config.ts +12 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-create.test.ts +37 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-delete.test.ts +45 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-deleted-not-in-sidebar.test.ts +44 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-detail-view.test.ts +46 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-edit-title.test.ts +48 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-expand-collapse.test.ts +50 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-list-in-sidebar.test.ts +37 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-reorder-dnd.test.ts +82 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-logout.test.ts +18 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-reject-invalid-token.test.ts +35 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-reject-used-token.test.ts +104 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-request-magic-link.test.ts +29 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-verify-via-pasted-token.test.ts +52 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-verify-via-url.test.ts +48 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth.setup.ts +55 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/constants.ts +13 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/dnd-inbox-to-area.test.ts +74 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/dnd-inbox-to-project.test.ts +73 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/dnd-move-to-inbox.test.ts +51 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/dnd-project-to-area.test.ts +76 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/dnd-project-to-project.test.ts +75 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/home.test.ts +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-complete.test.ts +53 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-completed-not-in-sidebar.test.ts +46 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-create-in-area.test.ts +55 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-create-top-level.test.ts +37 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-delete.test.ts +55 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-edit-notes-date.test.ts +69 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-edit-title.test.ts +48 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-move-into-area.test.ts +72 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-move-out-of-area.test.ts +76 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-reorder-top-level.test.ts +82 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-reorder-within-area.test.ts +91 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-uncomplete.test.ts +39 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-view-tasks.test.ts +48 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-complete-removes-from-active-views.test.ts +52 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-complete.test.ts +46 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-create-in-inbox.test.ts +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-create-in-project.test.ts +44 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-delete.test.ts +52 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-edit.test.ts +73 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-reorder-in-project.test.ts +81 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-reorder-inbox.test.ts +80 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-reorder-today.test.ts +103 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-uncomplete.test.ts +51 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-view-details.test.ts +51 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-active-sidebar-highlight.test.ts +38 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-inbox-unassigned-only.test.ts +43 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-navigate-to-completed.test.ts +59 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-navigate-to-inbox.test.ts +21 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-navigate-to-today.test.ts +42 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-navigate-to-upcoming.test.ts +59 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-sidebar-built-in-views.test.ts +23 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-today-shows-overdue.test.ts +48 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tsconfig.json +22 -0
- package/skills/maestro-examples/references/setlist/setlist-web/vite.config.ts +37 -0
- package/skills/maestro-examples/references/setlist/specs/app.md +69 -0
- package/skills/maestro-examples/references/setlist/specs/data-models.md +92 -0
- package/skills/maestro-examples/references/setlist/specs/database-schema.md +76 -0
- package/skills/maestro-examples/references/setlist/specs/drag-and-drop.md +89 -0
- package/skills/maestro-examples/references/setlist/specs/magic-link-login.md +300 -0
- package/skills/maestro-examples/references/setlist/specs/position-ordering.md +329 -0
- package/skills/maestro-examples/references/setlist/specs/sidebar.md +65 -0
- package/skills/maestro-examples/references/setlist/specs/use-cases.md +55 -0
- package/skills/maestro-examples/references/setlist/tsconfig.json +28 -0
- package/{dist → skills}/maestro-packages/SKILL.md +3 -3
- package/skills/maestro-packages/permissions.md +215 -0
- package/skills/maestro-packages/queue.md +442 -0
- package/skills/maestro-packages/recurring-jobs.md +238 -0
- package/skills/react-use-effect/SKILL.md +65 -0
- package/skills/react-use-effect/references/patterns.md +283 -0
- package/dist/maestro-packages/queue.md +0 -284
- package/dist/maestro-packages/recurring-jobs.md +0 -353
- package/dist/maestro-packages/tracing.md +0 -240
- /package/{dist → skills}/maestro-cli/SKILL.md +0 -0
- /package/{dist → skills}/maestro-packages/broadcast.md +0 -0
- /package/{dist → skills}/maestro-packages/cache-control.md +0 -0
- /package/{dist → skills}/maestro-packages/cache.md +0 -0
- /package/{dist → skills}/maestro-packages/config.md +0 -0
- /package/{dist → skills}/maestro-packages/context.md +0 -0
- /package/{dist → skills}/maestro-packages/crypt.md +0 -0
- /package/{dist → skills}/maestro-packages/db.md +0 -0
- /package/{dist → skills}/maestro-packages/events.md +0 -0
- /package/{dist → skills}/maestro-packages/exceptions.md +0 -0
- /package/{dist → skills}/maestro-packages/form.md +0 -0
- /package/{dist → skills}/maestro-packages/hash.md +0 -0
- /package/{dist → skills}/maestro-packages/helpers.md +0 -0
- /package/{dist → skills}/maestro-packages/log.md +0 -0
- /package/{dist → skills}/maestro-packages/mail.md +0 -0
- /package/{dist → skills}/maestro-packages/metrics.md +0 -0
- /package/{dist → skills}/maestro-packages/rate-limiting.md +0 -0
- /package/{dist → skills}/maestro-packages/react-router-file-routes.md +0 -0
- /package/{dist → skills}/maestro-packages/sql.md +0 -0
package/skills/maestro-examples/references/setlist/setlist-web/tests/views-navigate-to-inbox.test.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { test, expect } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
test('clicking Inbox in sidebar navigates to inbox view with active highlight', async ({ page }) => {
|
|
4
|
+
// Start from a different view so we can verify navigation
|
|
5
|
+
await page.goto('/today')
|
|
6
|
+
|
|
7
|
+
const nav = page.getByRole('navigation')
|
|
8
|
+
const inboxLink = nav.getByRole('link', { name: 'Inbox' })
|
|
9
|
+
|
|
10
|
+
// Click the Inbox link
|
|
11
|
+
await inboxLink.click()
|
|
12
|
+
|
|
13
|
+
// Verify URL changed to /inbox
|
|
14
|
+
await expect(page).toHaveURL('/inbox')
|
|
15
|
+
|
|
16
|
+
// Verify Inbox heading is visible
|
|
17
|
+
await expect(page.getByRole('heading', { name: 'Inbox' })).toBeVisible()
|
|
18
|
+
|
|
19
|
+
// Verify the Inbox link is highlighted as active
|
|
20
|
+
await expect(inboxLink).toHaveClass(/active/)
|
|
21
|
+
})
|
package/skills/maestro-examples/references/setlist/setlist-web/tests/views-navigate-to-today.test.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { test, expect } from '@playwright/test'
|
|
2
|
+
import { H } from '@setlist/services'
|
|
3
|
+
import { TEST_CONSTANTS, localDate } from './constants'
|
|
4
|
+
|
|
5
|
+
const userId = TEST_CONSTANTS.userId
|
|
6
|
+
|
|
7
|
+
const today = localDate()
|
|
8
|
+
|
|
9
|
+
const seedData = H.SeedPipe(
|
|
10
|
+
H.TaskSeed({ id: 9110, userId, title: 'NavToday Task', scheduledDate: today, listPosition: 'a0', scheduledPosition: 'a0' })
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
test.beforeAll(async () => {
|
|
14
|
+
await seedData.setup()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test.afterAll(async () => {
|
|
18
|
+
await seedData.teardown()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('clicking Today in sidebar navigates to today view with active highlight', async ({ page }) => {
|
|
22
|
+
// Start from a different view so we can verify navigation
|
|
23
|
+
await page.goto('/inbox')
|
|
24
|
+
|
|
25
|
+
const nav = page.getByRole('navigation')
|
|
26
|
+
const todayLink = nav.getByRole('link', { name: 'Today' })
|
|
27
|
+
|
|
28
|
+
// Click the Today link
|
|
29
|
+
await todayLink.click()
|
|
30
|
+
|
|
31
|
+
// Verify URL changed to /today
|
|
32
|
+
await expect(page).toHaveURL('/today')
|
|
33
|
+
|
|
34
|
+
// Verify Today heading is visible
|
|
35
|
+
await expect(page.getByText(/Good (morning|afternoon|evening)/)).toBeVisible()
|
|
36
|
+
|
|
37
|
+
// Verify the seeded task is visible
|
|
38
|
+
await expect(page.getByRole('row', { name: 'NavToday Task' })).toBeVisible()
|
|
39
|
+
|
|
40
|
+
// Verify the Today link is highlighted as active
|
|
41
|
+
await expect(todayLink).toHaveClass(/active/)
|
|
42
|
+
})
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { test, expect } from '@playwright/test'
|
|
2
|
+
import { H } from '@setlist/services'
|
|
3
|
+
import { TEST_CONSTANTS, localDate } from './constants'
|
|
4
|
+
|
|
5
|
+
const userId = TEST_CONSTANTS.userId
|
|
6
|
+
|
|
7
|
+
const tomorrow = localDate(1)
|
|
8
|
+
const nextWeek = localDate(7)
|
|
9
|
+
|
|
10
|
+
const seedData = H.SeedPipe(
|
|
11
|
+
H.TaskSeed({
|
|
12
|
+
id: 9130,
|
|
13
|
+
userId,
|
|
14
|
+
title: 'Tomorrow Task',
|
|
15
|
+
scheduledDate: tomorrow,
|
|
16
|
+
listPosition: 'a0',
|
|
17
|
+
scheduledPosition: 'a0'
|
|
18
|
+
}),
|
|
19
|
+
H.TaskSeed({
|
|
20
|
+
id: 9131,
|
|
21
|
+
userId,
|
|
22
|
+
title: 'Next Week Task',
|
|
23
|
+
scheduledDate: nextWeek,
|
|
24
|
+
listPosition: 'a1',
|
|
25
|
+
scheduledPosition: 'a0'
|
|
26
|
+
})
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
test.beforeAll(async () => {
|
|
30
|
+
await seedData.setup()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test.afterAll(async () => {
|
|
34
|
+
await seedData.teardown()
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('clicking Upcoming in sidebar navigates to upcoming view with tasks grouped by date', async ({ page }) => {
|
|
38
|
+
// Start from a different view so we can verify navigation
|
|
39
|
+
await page.goto('/inbox')
|
|
40
|
+
|
|
41
|
+
const nav = page.getByRole('navigation')
|
|
42
|
+
const upcomingLink = nav.getByRole('link', { name: 'Upcoming' })
|
|
43
|
+
|
|
44
|
+
// Click the Upcoming link
|
|
45
|
+
await upcomingLink.click()
|
|
46
|
+
|
|
47
|
+
// Verify URL changed to /upcoming
|
|
48
|
+
await expect(page).toHaveURL('/upcoming')
|
|
49
|
+
|
|
50
|
+
// Verify Upcoming heading is visible
|
|
51
|
+
await expect(page.getByRole('heading', { name: 'Upcoming' })).toBeVisible()
|
|
52
|
+
|
|
53
|
+
// Verify the seeded tasks are visible
|
|
54
|
+
await expect(page.getByRole('row', { name: 'Tomorrow Task' })).toBeVisible()
|
|
55
|
+
await expect(page.getByRole('row', { name: 'Next Week Task' })).toBeVisible()
|
|
56
|
+
|
|
57
|
+
// Verify the Upcoming link is highlighted as active
|
|
58
|
+
await expect(upcomingLink).toHaveClass(/active/)
|
|
59
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { test, expect } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
test('sidebar displays all four built-in views in order', async ({ page }) => {
|
|
4
|
+
await page.goto('/inbox')
|
|
5
|
+
|
|
6
|
+
const nav = page.getByRole('navigation')
|
|
7
|
+
|
|
8
|
+
// Verify all four built-in view links are visible
|
|
9
|
+
await expect(nav.getByRole('link', { name: 'Inbox' })).toBeVisible()
|
|
10
|
+
await expect(nav.getByRole('link', { name: 'Today' })).toBeVisible()
|
|
11
|
+
await expect(nav.getByRole('link', { name: 'Upcoming' })).toBeVisible()
|
|
12
|
+
await expect(nav.getByRole('link', { name: 'Completed' })).toBeVisible()
|
|
13
|
+
|
|
14
|
+
// Verify order: Inbox, Today, Upcoming, Completed
|
|
15
|
+
const links = nav.locator('a')
|
|
16
|
+
const allTexts = await links.allTextContents()
|
|
17
|
+
const viewNames = ['Inbox', 'Today', 'Upcoming', 'Completed']
|
|
18
|
+
const indices = viewNames.map((name) => allTexts.findIndex((text) => text.includes(name)))
|
|
19
|
+
|
|
20
|
+
for (let i = 1; i < indices.length; i++) {
|
|
21
|
+
expect(indices[i]!, `${viewNames[i]} should appear after ${viewNames[i - 1]}`).toBeGreaterThan(indices[i - 1]!)
|
|
22
|
+
}
|
|
23
|
+
})
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { test, expect } from '@playwright/test'
|
|
2
|
+
import { H } from '@setlist/services'
|
|
3
|
+
import { TEST_CONSTANTS, localDate } from './constants'
|
|
4
|
+
|
|
5
|
+
const userId = TEST_CONSTANTS.userId
|
|
6
|
+
|
|
7
|
+
const today = localDate()
|
|
8
|
+
const yesterday = localDate(-1)
|
|
9
|
+
|
|
10
|
+
const seedData = H.SeedPipe(
|
|
11
|
+
H.TaskSeed({
|
|
12
|
+
id: 9120,
|
|
13
|
+
userId,
|
|
14
|
+
title: 'Overdue Task',
|
|
15
|
+
scheduledDate: yesterday,
|
|
16
|
+
listPosition: 'a0',
|
|
17
|
+
scheduledPosition: 'a0'
|
|
18
|
+
}),
|
|
19
|
+
H.TaskSeed({
|
|
20
|
+
id: 9121,
|
|
21
|
+
userId,
|
|
22
|
+
title: 'OverdueView Today Task',
|
|
23
|
+
scheduledDate: today,
|
|
24
|
+
listPosition: 'a1',
|
|
25
|
+
scheduledPosition: 'a1'
|
|
26
|
+
})
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
test.beforeAll(async () => {
|
|
30
|
+
await seedData.setup()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test.afterAll(async () => {
|
|
34
|
+
await seedData.teardown()
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
test('today view shows overdue tasks alongside tasks scheduled for today', async ({ page }) => {
|
|
38
|
+
await page.goto('/today')
|
|
39
|
+
|
|
40
|
+
// Verify the Today heading is visible
|
|
41
|
+
await expect(page.getByText(/Good (morning|afternoon|evening)/)).toBeVisible()
|
|
42
|
+
|
|
43
|
+
// The overdue task (yesterday) should be visible
|
|
44
|
+
await expect(page.getByRole('row', { name: 'Overdue Task' })).toBeVisible()
|
|
45
|
+
|
|
46
|
+
// The today task should also be visible
|
|
47
|
+
await expect(page.getByRole('row', { name: 'OverdueView Today Task' })).toBeVisible()
|
|
48
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"types": ["vite/client"],
|
|
8
|
+
"rootDirs": [".", ".react-router/types"],
|
|
9
|
+
"paths": {
|
|
10
|
+
"~/*": ["./app/*"]
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"include": [
|
|
14
|
+
"app",
|
|
15
|
+
"tests",
|
|
16
|
+
"vite.config.ts",
|
|
17
|
+
"react-router.config.ts",
|
|
18
|
+
".react-router",
|
|
19
|
+
"./environment.d.ts",
|
|
20
|
+
"playwright.config.ts"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { reactRouter } from '@react-router/dev/vite'
|
|
2
|
+
import { sentryReactRouter } from '@sentry/react-router'
|
|
3
|
+
import tailwindcss from '@tailwindcss/vite'
|
|
4
|
+
import { iconsSpritesheet } from 'vite-plugin-icons-spritesheet'
|
|
5
|
+
import { defineConfig } from 'vite'
|
|
6
|
+
import tsconfigPaths from 'vite-tsconfig-paths'
|
|
7
|
+
import { envOnlyMacros } from 'vite-env-only'
|
|
8
|
+
|
|
9
|
+
export default defineConfig((config) => ({
|
|
10
|
+
plugins: [
|
|
11
|
+
envOnlyMacros(),
|
|
12
|
+
tsconfigPaths(),
|
|
13
|
+
tailwindcss(),
|
|
14
|
+
reactRouter(),
|
|
15
|
+
sentryReactRouter(
|
|
16
|
+
{
|
|
17
|
+
org: process.env.SENTRY_ORG,
|
|
18
|
+
project: process.env.SENTRY_PROJECT,
|
|
19
|
+
authToken: process.env.SENTRY_AUTH_TOKEN
|
|
20
|
+
},
|
|
21
|
+
config
|
|
22
|
+
),
|
|
23
|
+
iconsSpritesheet({
|
|
24
|
+
inputDir: 'icons',
|
|
25
|
+
outputDir: 'app/icons',
|
|
26
|
+
fileName: 'sprite.svg',
|
|
27
|
+
withTypes: true,
|
|
28
|
+
typesOutputFile: 'app/icons/types.ts',
|
|
29
|
+
iconNameTransformer: (name) => name,
|
|
30
|
+
formatter: 'prettier'
|
|
31
|
+
})
|
|
32
|
+
],
|
|
33
|
+
server: {
|
|
34
|
+
port: 3000,
|
|
35
|
+
strictPort: true
|
|
36
|
+
}
|
|
37
|
+
}))
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# App Requirements
|
|
2
|
+
|
|
3
|
+
A personal task manager modeled after Things. Users organize their work into tasks, projects, and areas. Tasks have titles, notes, scheduled dates, and can be completed or reordered via drag-and-drop.
|
|
4
|
+
|
|
5
|
+
## Areas
|
|
6
|
+
|
|
7
|
+
An area is a sphere of responsibility — an ongoing concern with no end date (e.g. "Health", "Work", "Finance").
|
|
8
|
+
|
|
9
|
+
- An area has a title (required)
|
|
10
|
+
- An area contains zero or more projects and zero or more standalone tasks (tasks not in a project)
|
|
11
|
+
- Areas cannot be completed — they are ongoing
|
|
12
|
+
- An area can be deleted
|
|
13
|
+
- Areas appear in the sidebar and can be reordered via drag-and-drop
|
|
14
|
+
|
|
15
|
+
## Projects
|
|
16
|
+
|
|
17
|
+
A project is a collection of related tasks that work toward a specific goal. Projects are finite — they have a clear endpoint.
|
|
18
|
+
|
|
19
|
+
- A project has a title (required) and notes (optional)
|
|
20
|
+
- A project can have a scheduled date
|
|
21
|
+
- A project belongs to at most one area
|
|
22
|
+
- A project contains zero or more tasks, ordered by the user via drag-and-drop
|
|
23
|
+
- A project can be completed — completing a project does not automatically complete its tasks
|
|
24
|
+
- A project can be deleted
|
|
25
|
+
- Projects appear in the sidebar and can be reordered via drag-and-drop
|
|
26
|
+
|
|
27
|
+
## Tasks
|
|
28
|
+
|
|
29
|
+
A task is the core unit of work.
|
|
30
|
+
|
|
31
|
+
- A task has a title (required) and notes (optional, rich text)
|
|
32
|
+
- A task can have a scheduled date — the date the user plans to work on it
|
|
33
|
+
- A task can be completed by checking a checkbox; completed tasks move to a "Completed" view
|
|
34
|
+
- A task can be deleted
|
|
35
|
+
- Tasks belong to the Inbox by default if not assigned to a project or area or scheduled for a day
|
|
36
|
+
- Tasks can be reordered via drag-and-drop within any list they appear in
|
|
37
|
+
- A task can optionally belong to one project
|
|
38
|
+
- A task can optionally belong to one area (inherited from its project, or assigned directly if the task has no project)
|
|
39
|
+
|
|
40
|
+
## Views
|
|
41
|
+
|
|
42
|
+
The app provides several built-in views for browsing tasks:
|
|
43
|
+
|
|
44
|
+
- **Inbox** — tasks that have not been assigned to a project or area. The default landing place for new tasks. Tasks are ordered by the user via drag-and-drop.
|
|
45
|
+
- **Today** — tasks whose scheduled date is today, plus overdue tasks. Ordered by the user via drag-and-drop.
|
|
46
|
+
- **Upcoming** — a calendar-style view showing tasks grouped by their scheduled date, looking forward in time
|
|
47
|
+
- **Completed** — all completed tasks, shown in reverse chronological order of completion
|
|
48
|
+
|
|
49
|
+
## Dates
|
|
50
|
+
|
|
51
|
+
- **Scheduled date**: the date the user intends to start or work on the task. Setting a scheduled date to today causes the task to appear in the Today view.
|
|
52
|
+
|
|
53
|
+
## Drag-and-Drop Reordering
|
|
54
|
+
|
|
55
|
+
- Tasks can be reordered via drag-and-drop within any list: Inbox, Today, a project's task list, or an area's task list
|
|
56
|
+
- Projects and areas can be reordered in the sidebar via drag-and-drop
|
|
57
|
+
- A task can be moved into a different project or area by dragging it
|
|
58
|
+
- Reordering persists across sessions
|
|
59
|
+
|
|
60
|
+
## Completion
|
|
61
|
+
|
|
62
|
+
- Clicking a task's checkbox marks it as complete with a timestamp
|
|
63
|
+
- Completed tasks disappear from active views and move to the Completed view
|
|
64
|
+
- A completed task can be uncompleted, returning it to its original location
|
|
65
|
+
- Projects can also be completed via a checkbox; a completed project disappears from the sidebar and moves to the Completed view
|
|
66
|
+
|
|
67
|
+
## Authentication
|
|
68
|
+
|
|
69
|
+
Authentication uses magic links — no passwords. A user enters their email, receives a link, and clicking it logs them in. The email also includes the raw token as a copyable string so the user can paste it into a login form on a different device. Uses `@maestro-js/auth` with `loginById()` after validating a selector/verifier token pair (same pattern as password reset links). All tasks, projects, and areas belong to the authenticated user. There is no sharing or collaboration — this is a single-user-per-account app.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Data Models
|
|
2
|
+
|
|
3
|
+
Zod schemas for the personal task manager. Each section defines a zod model. Note: zod models are not necessarily one-to-one with database tables.
|
|
4
|
+
|
|
5
|
+
## Users
|
|
6
|
+
|
|
7
|
+
A user is a single account holder.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const userModel = z.object({
|
|
11
|
+
id: z.number(),
|
|
12
|
+
email: z.string(),
|
|
13
|
+
createdDate: isoZ.instant(),
|
|
14
|
+
lastModifiedDate: isoZ.instant()
|
|
15
|
+
})
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Magic Links
|
|
19
|
+
|
|
20
|
+
Authentication uses magic links sent via email — no passwords. The flow mirrors password reset tokens: a selector/verifier pair is generated, the verifier hash is stored, and the full token is emailed as a link. Clicking the link validates the token and calls `Auth.loginById()` to establish a session. The email also includes the raw token as a copyable string so users can paste it into a login form on a different device.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
const magicLinkModel = z.object({
|
|
24
|
+
id: z.number(),
|
|
25
|
+
userId: z.number(),
|
|
26
|
+
selector: z.string(),
|
|
27
|
+
verifierHash: z.string(),
|
|
28
|
+
usedDate: isoZ.instant().nullable(),
|
|
29
|
+
expirationDate: isoZ.instant(),
|
|
30
|
+
createdDate: isoZ.instant()
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Areas
|
|
35
|
+
|
|
36
|
+
An area is an ongoing sphere of responsibility with no end date.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
const areaModel = z.object({
|
|
40
|
+
id: z.number(),
|
|
41
|
+
userId: z.number(),
|
|
42
|
+
title: z.string(),
|
|
43
|
+
position: z.string(),
|
|
44
|
+
deletedDate: isoZ.instant().nullable(),
|
|
45
|
+
createdDate: isoZ.instant(),
|
|
46
|
+
lastModifiedDate: isoZ.instant()
|
|
47
|
+
})
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Projects
|
|
51
|
+
|
|
52
|
+
A project is a finite collection of tasks working toward a specific goal. A project optionally belongs to an area. Top-level projects (no area) share the sidebar position space with areas.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
const projectModel = z.object({
|
|
56
|
+
id: z.number(),
|
|
57
|
+
userId: z.number(),
|
|
58
|
+
areaId: z.number().nullable(),
|
|
59
|
+
title: z.string(),
|
|
60
|
+
notes: z.string().nullable(),
|
|
61
|
+
scheduledDate: isoZ.date().nullable(),
|
|
62
|
+
position: z.string(),
|
|
63
|
+
completedDate: isoZ.instant().nullable(),
|
|
64
|
+
deletedDate: isoZ.instant().nullable(),
|
|
65
|
+
createdDate: isoZ.instant(),
|
|
66
|
+
lastModifiedDate: isoZ.instant()
|
|
67
|
+
})
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Tasks
|
|
71
|
+
|
|
72
|
+
A task is the core unit of work. A task optionally belongs to a project and/or an area. Tasks not assigned to a project, area, or scheduled date appear in the Inbox.
|
|
73
|
+
|
|
74
|
+
`listPosition` orders the task within its container (project, area, or inbox). Moving a task between containers resets its `listPosition`. `scheduledPosition` orders the task within its scheduled date. Rescheduling a task resets its `scheduledPosition`.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const taskModel = z.object({
|
|
78
|
+
id: z.number(),
|
|
79
|
+
userId: z.number(),
|
|
80
|
+
projectId: z.number().nullable(),
|
|
81
|
+
areaId: z.number().nullable(),
|
|
82
|
+
title: z.string(),
|
|
83
|
+
notes: z.string().nullable(),
|
|
84
|
+
scheduledDate: isoZ.date().nullable(),
|
|
85
|
+
listPosition: z.string(),
|
|
86
|
+
scheduledPosition: z.string().nullable(),
|
|
87
|
+
completedDate: isoZ.instant().nullable(),
|
|
88
|
+
deletedDate: isoZ.instant().nullable(),
|
|
89
|
+
createdDate: isoZ.instant(),
|
|
90
|
+
lastModifiedDate: isoZ.instant()
|
|
91
|
+
})
|
|
92
|
+
```
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Database Schema
|
|
2
|
+
|
|
3
|
+
MySQL schema for the personal task manager. Derived from the zod models in `data-models.md`.
|
|
4
|
+
|
|
5
|
+
## Tables
|
|
6
|
+
|
|
7
|
+
```sql
|
|
8
|
+
CREATE TABLE users (
|
|
9
|
+
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
10
|
+
email VARCHAR(255) NOT NULL,
|
|
11
|
+
credentialsInvalidBefore DATETIME(3),
|
|
12
|
+
createdDate DATETIME(3) NOT NULL,
|
|
13
|
+
lastModifiedDate DATETIME(3) NOT NULL,
|
|
14
|
+
UNIQUE KEY uq_users_email (email)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
CREATE TABLE magicLinks (
|
|
18
|
+
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
19
|
+
userId INT UNSIGNED NOT NULL,
|
|
20
|
+
selector VARCHAR(255) NOT NULL,
|
|
21
|
+
verifierHash VARCHAR(255) NOT NULL,
|
|
22
|
+
usedDate DATETIME(3),
|
|
23
|
+
expirationDate DATETIME(3) NOT NULL,
|
|
24
|
+
createdDate DATETIME(3) NOT NULL,
|
|
25
|
+
UNIQUE KEY uq_magicLinks_selector (selector),
|
|
26
|
+
CONSTRAINT fk_magicLinks_userId FOREIGN KEY (userId) REFERENCES users (id)
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE TABLE areas (
|
|
30
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
31
|
+
userId INT UNSIGNED NOT NULL,
|
|
32
|
+
title VARCHAR(255) NOT NULL,
|
|
33
|
+
position VARCHAR(255) NOT NULL,
|
|
34
|
+
deletedDate DATETIME(3),
|
|
35
|
+
createdDate DATETIME(3) NOT NULL,
|
|
36
|
+
lastModifiedDate DATETIME(3) NOT NULL,
|
|
37
|
+
CONSTRAINT fk_areas_userId FOREIGN KEY (userId) REFERENCES users (id)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
CREATE TABLE projects (
|
|
41
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
42
|
+
userId INT UNSIGNED NOT NULL,
|
|
43
|
+
areaId BIGINT UNSIGNED,
|
|
44
|
+
title VARCHAR(255) NOT NULL,
|
|
45
|
+
notes TEXT,
|
|
46
|
+
scheduledDate DATE,
|
|
47
|
+
position VARCHAR(255) NOT NULL,
|
|
48
|
+
completedDate DATETIME(3),
|
|
49
|
+
deletedDate DATETIME(3),
|
|
50
|
+
createdDate DATETIME(3) NOT NULL,
|
|
51
|
+
lastModifiedDate DATETIME(3) NOT NULL,
|
|
52
|
+
CONSTRAINT fk_projects_userId FOREIGN KEY (userId) REFERENCES users (id),
|
|
53
|
+
CONSTRAINT fk_projects_areaId FOREIGN KEY (areaId) REFERENCES areas (id)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
CREATE TABLE tasks (
|
|
57
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
58
|
+
userId INT UNSIGNED NOT NULL,
|
|
59
|
+
projectId BIGINT UNSIGNED,
|
|
60
|
+
areaId BIGINT UNSIGNED,
|
|
61
|
+
title VARCHAR(255) NOT NULL,
|
|
62
|
+
notes TEXT,
|
|
63
|
+
scheduledDate DATE,
|
|
64
|
+
listPosition VARCHAR(255) NOT NULL,
|
|
65
|
+
scheduledPosition VARCHAR(255),
|
|
66
|
+
completedDate DATETIME(3),
|
|
67
|
+
deletedDate DATETIME(3),
|
|
68
|
+
createdDate DATETIME(3) NOT NULL,
|
|
69
|
+
lastModifiedDate DATETIME(3) NOT NULL,
|
|
70
|
+
KEY idx_tasks_userId_scheduledDate (userId, scheduledDate),
|
|
71
|
+
KEY idx_tasks_userId_completedDate (userId, completedDate),
|
|
72
|
+
CONSTRAINT fk_tasks_userId FOREIGN KEY (userId) REFERENCES users (id),
|
|
73
|
+
CONSTRAINT fk_tasks_projectId FOREIGN KEY (projectId) REFERENCES projects (id),
|
|
74
|
+
CONSTRAINT fk_tasks_areaId FOREIGN KEY (areaId) REFERENCES areas (id)
|
|
75
|
+
);
|
|
76
|
+
```
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Drag-and-Drop Technical Writeup
|
|
2
|
+
|
|
3
|
+
Implementation plan for drag-and-drop reordering across the Setlist app using `@dnd-kit/core` + `@dnd-kit/sortable` + `@dnd-kit/utilities`.
|
|
4
|
+
|
|
5
|
+
## Surfaces
|
|
6
|
+
|
|
7
|
+
There are three distinct drag-and-drop contexts:
|
|
8
|
+
|
|
9
|
+
| Context | Draggable Items | Drop Targets | Cross-container? |
|
|
10
|
+
| ----------------------------------------------------- | ------------------------- | ---------------------------------------------- | ----------------------------------------- |
|
|
11
|
+
| Sidebar | Areas, top-level projects | Reorder within sidebar; drop project onto area | Yes (project into/out of area) |
|
|
12
|
+
| Task list (Inbox, Today, Project detail, Area detail) | Tasks | Reorder within the current list | No (reorder only) |
|
|
13
|
+
| Task cross-container move | Tasks | Sidebar areas and projects | Yes (move task to different project/area) |
|
|
14
|
+
|
|
15
|
+
## Position Strategy
|
|
16
|
+
|
|
17
|
+
See [position-ordering.md](position-ordering.md) for the fractional indexing algorithm, `generateKeyBetween` implementation, position column definitions, and usage examples (reorder, insert, cross-container moves, new item creation).
|
|
18
|
+
|
|
19
|
+
## Frontend Architecture
|
|
20
|
+
|
|
21
|
+
### DnD Kit Setup
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
<DndContext> // one per page/layout
|
|
25
|
+
<SortableContext items={...}> // one per sortable list
|
|
26
|
+
<SortableItem /> // wraps each draggable item
|
|
27
|
+
</SortableContext>
|
|
28
|
+
</DndContext>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Sensors
|
|
32
|
+
|
|
33
|
+
Use `useSensor(PointerSensor, { activationConstraint: { distance: 5 } })` to prevent accidental drags on click. Add `KeyboardSensor` for accessibility.
|
|
34
|
+
|
|
35
|
+
### Collision Detection
|
|
36
|
+
|
|
37
|
+
- **Single-list reorder**: `closestCenter` (default) works well
|
|
38
|
+
- **Cross-container moves** (task to sidebar project/area): use `pointerWithin` or `rectIntersection` so the drop target is the container the pointer is inside
|
|
39
|
+
|
|
40
|
+
### Overlay
|
|
41
|
+
|
|
42
|
+
Use `<DragOverlay>` to render a styled clone of the dragged item. This avoids layout shifts in the source list during the drag.
|
|
43
|
+
|
|
44
|
+
### Optimistic Updates
|
|
45
|
+
|
|
46
|
+
1. `onDragEnd` fires with `active` (dragged item) and `over` (drop target)
|
|
47
|
+
2. Immediately reorder the local state (React state or cache) so the UI updates without waiting for the server
|
|
48
|
+
3. Fire the API call in the background
|
|
49
|
+
4. On failure, roll back local state and show an error toast
|
|
50
|
+
|
|
51
|
+
## Use Case Mapping
|
|
52
|
+
|
|
53
|
+
| Use Case | Drag Source | Drop Target | Fields Updated |
|
|
54
|
+
| --------------------------- | ------------------ | --------------------------- | ---------------------------------------------------------------- |
|
|
55
|
+
| AR5 — Reorder areas | Area in sidebar | Between areas in sidebar | `areas.position` |
|
|
56
|
+
| PR8 — Reorder projects | Project in sidebar | Between projects in sidebar | `projects.position` |
|
|
57
|
+
| PR4 — Move project to area | Project in sidebar | Area in sidebar | `projects.position`, `projects.areaId` |
|
|
58
|
+
| T8 — Reorder tasks in list | Task in list view | Between tasks in same list | `tasks.listPosition` |
|
|
59
|
+
| T8 — Reorder tasks in Today | Task in Today view | Between tasks in Today | `tasks.scheduledPosition` |
|
|
60
|
+
| T4 — Move task to project | Task in any list | Project in sidebar | `tasks.listPosition`, `tasks.projectId`, `tasks.areaId` |
|
|
61
|
+
| T4 — Move task to area | Task in any list | Area in sidebar | `tasks.listPosition`, `tasks.areaId`, `tasks.projectId` (nulled) |
|
|
62
|
+
|
|
63
|
+
## Sidebar Mixed List
|
|
64
|
+
|
|
65
|
+
The sidebar contains both areas and top-level projects in a single sortable list. Since both entity types share the same position space, they interleave by `position` value.
|
|
66
|
+
|
|
67
|
+
To model this with dnd-kit, use a single `<SortableContext>` with a unified items array:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
const sidebarItems = [...areas, ...topLevelProjects]
|
|
71
|
+
.sort((a, b) => a.position.localeCompare(b.position))
|
|
72
|
+
.map(item => ({ id: `${'areaId' in item ? 'project' : 'area'}-${item.id}`, ...item }))
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Prefixed IDs (`area-1`, `project-5`) let `onDragEnd` determine the entity type and call the correct API.
|
|
76
|
+
|
|
77
|
+
## Edge Cases
|
|
78
|
+
|
|
79
|
+
- **Completed/deleted items**: exclude from sortable lists — they don't participate in drag-and-drop
|
|
80
|
+
- **Moving a task out of inbox**: when a task gains a `projectId` or `areaId`, it's no longer an inbox task. No special handling needed — inbox is defined by the absence of project, area, and scheduled date.
|
|
81
|
+
- **Moving a task to inbox**: set `projectId` and `areaId` to `null`. The task reappears in inbox if it also has no `scheduledDate`.
|
|
82
|
+
|
|
83
|
+
## Dependencies
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
@dnd-kit/core
|
|
87
|
+
@dnd-kit/sortable
|
|
88
|
+
@dnd-kit/utilities
|
|
89
|
+
```
|