Commit Graph
83 Commits
Author SHA1 Message Date
NeilClack ec826093eb Expose dynamic audio on the v2 schedule API 2026-09-11 18:41:57 -05:00
NeilClack 96a1342c10 Add Enable Dynamic Audio option to schedule blocks 2026-09-11 18:41:53 -05:00
NeilClack 468a65a688 Add dynamic audio flag to schedule blocks 2026-09-11 18:41:46 -05:00
NeilClack e934a98f00 Use a 12-hour clock with AM/PM selects in the block modal 2026-09-11 18:30:26 -05:00
NeilClack 15bb51582b Move Cancel left and rename Back to Accept in the block modal 2026-09-11 18:30:08 -05:00
NeilClack 46d7cf66b8 Render overnight blocks across midnight in the day view 2026-09-11 18:24:54 -05:00
NeilClack 177b7bb13a Flag overnight blocks in the v2 schedule API 2026-09-11 18:24:51 -05:00
NeilClack 750a9286c9 Support overnight blocks in schedule validation 2026-09-11 18:24:48 -05:00
NeilClack 5f4116b8e8 Add schedule page with block editor and proclamation browser 2026-09-11 18:16:06 -05:00
NeilClack 545fb22910 Add v2 schedule API endpoint 2026-09-11 18:16:04 -05:00
NeilClack 4922e941ae Add schedule validation and service layer 2026-09-11 18:16:00 -05:00
NeilClack e6b492a335 Add schedule data model and migration 2026-09-11 18:15:57 -05:00
NeilClack 960673bbc6 Add a site-wide dark mode
Build and Push to Digital Ocean Container Registry / build-and-push (push) Failing after 4s
Build and Push to Digital Ocean Container Registry / migrate (push) Skipped
2026-09-11 12:49:46 -05:00
NeilClack d16965dab6 Add AuditLog table and Prisma audit extension 2026-09-10 15:10:11 -05:00
NeilClack 0cb4b2148a Expose roleId on the Better Auth session user 2026-09-10 14:59:28 -05:00
NeilClack f6b8cad15e Add subject to password reset email 2026-09-10 14:14:45 -05:00
NeilClack 29d53af8dd Remove unauthenticated /send email endpoint 2026-09-10 14:14:44 -05:00
NeilClack 84c905c9ff Add shared registration invite helper and use it for admin-created users 2026-09-10 14:08:51 -05:00
NeilClack 5ec3018f8b Email a set-password link when an admin creates a user 2026-09-10 13:42:33 -05:00
NeilClack 0175cab0b4 Add lastValidatedAt to license keys 2026-09-10 13:18:15 -05:00
NeilClack 1aecc51bbd Replace account and license-keys pages with profile page and dashboard 2026-09-10 13:11:41 -05:00
NeilClack f50eb34769 Add createdAt to license keys 2026-09-10 13:11:34 -05:00
NeilClack 4a1777de87 Keep legacy subscription tables as unmanaged instead of dropping them 2026-09-10 11:48:49 -05:00
NeilClack d89fc6837c Add default roleId 4 to new users 2026-09-10 11:48:20 -05:00
NeilClack 91d162c746 Rebuild admin pages around DataTable/AdminModal; restructure categories/groups and v2 groups API
Remove the generic $lib/svelte-admin CRUD layer and AdminTable.svelte; each
admin route now owns its own form/modal logic. Add DataTable.svelte,
superform-errors.ts, and profile-specific modal/field components.

Flatten proclamation categories/groups and drop subscription levels; add the
v2 groups API; update v1/v2 endpoints, serializers, auth, and regenerated
Prisma client with the new migrations.

Document the overhaul plan in docs/ADMIN_OVERHAUL.md.
2026-09-10 09:38:01 -05:00
NeilClack 64f7070ad7 Build API v2 2026-08-07 14:06:20 -05:00
NeilClack b746d89448 Fix non-serializable accessFilter in admin load, add error boundary and tests 2026-07-17 14:52:09 -05:00
NeilClack c52474d69b Update environment variables in resend module 2026-07-17 12:42:42 -05:00
NeilClack fd630ff714 Resolve build errors 2026-07-17 11:51:14 -05:00
NeilClack c860596f96 Merge dev 2026-07-17 11:06:32 -05:00
NeilClack 65ae7675ba Complete docker build in preparation for app-runner deployment 2026-07-16 22:01:36 -05:00
NeilClack 2d0cf98ed3 fix tests: add subject to email-verification assertion, add url + api-key mock to hooks test 2026-07-08 15:36:11 -05:00
NeilClack 92f54e829e add subject line to verification email 2026-07-08 15:29:45 -05:00
NeilClack 55a29b9c1a feat: wire GHL webhook to Resend email templates
- Replace raw Resend text emails with sendMail using Resend templates
- automated-user-registration template: firstName, tempPassword,
  verifyUrl, loginUrl
- license-key-delivery template: firstName, license_key
- Remove requestPasswordReset call (temp password is the one-time
  credential; verification link handles email confirmation)
- Add .catch() to Better Auth email callbacks to prevent unhandled
  rejections from missing templates crashing the server
2026-07-08 15:01:08 -05:00
NeilClack 4d21288511 api: switch license endpoint to POST/JSON, fix active check, add key copy button
- Change /api/v1/license from GET with query params to POST with JSON body
- Request body uses license_key and email_address
- Response returns key, email_address, subscription_level
- Add active check (reject deactivated license keys)
- Exclude /api/v1/automations/ from API key auth (GHL webhook)
- Add copyableFields prop to AdminTable with clipboard icon
- Enable copy button on license key field in license-keys admin page
2026-07-08 14:11:01 -05:00
NeilClack 46b2cdf53d api: API key authentication with rotation and grace period
- Add ApiKey Prisma model (keyHash, expiresAt, revokedAt)
- Protect /api/v1/* routes with Authorization: Bearer header check in hooks
- create rotateApiKey() utility: normal (48h grace) and emergency (immediate)
- Add Super-only /admin/api-keys page for key rotation with one-time reveal
- Fix roleId check by using parent layout's DB-fetched adminUser
- Add API Keys link to admin sidebar
2026-07-08 13:18:19 -05:00
NeilClack 6266be0edf admin: category drag-and-drop reorder + modal-based license key management
- Add sortOrder column to ProclamationCategory with migration
- Implement drag-and-drop reorder in AdminTable with persist-to-DB
- Refactor AdminTable to use $derived + dragOverride (no $effect sync)
- Replace window.location.reload with invalidateAll for reorder

- Convert license key create to modal with subscription level dropdown
- Add LicenseKeyForm.svelte following the CategoryForm pattern
- Add replace action (delete + generate new key with same level)
- Remove deactivateOld checkbox; each key has its own level
- Use use:enhance with update() to refresh list after create/replace
2026-07-08 12:59:55 -05:00
NeilClack 93d941569e proclamation-categories: sub-category management inline in parent form
- Registry: Remove 'parent.name' from listFields (all shown records
  are top-level with no parent), remove 'parent: true' from include
  since unused
- +page.server.ts: Custom load filters to parentId=null (top-level
  only); custom upsert syncs children (create/update/delete) and
  handles P2002 duplicate-name errors; custom delete cascades to
  children first to avoid FK constraint violations
- CategoryForm.svelte: Replace parentId select dropdown with dynamic
  list of sub-category inputs. Each row has a name field and Remove
  button. Pre-populates from record.children when editing existing
  categories. Add Sub-category button appends new rows
- +page.svelte: Remove unused relationOptionsData prop from
  CategoryForm; rename submit button label from 'Update' to 'Save'
- prisma: Add ProclamationCategorySubscriptionLevel join table
  migration and regenerate client
- General: Update TipTap mock, Toast, license-keys page, proclamations
  server/route tests, README, AGENTS.md, and other admin forms
2026-07-08 10:31:28 -05:00
NeilClack 4cef38a1ab Commit 2: Delete AdminForm.svelte and AdminPage.svelte 2026-07-07 21:01:02 -05:00
NeilClack 22b6adee3f Commit 1: Create individual form components per route, remove generic AdminForm dependency
- Add per-route form components: UserRoleForm, UserForm,
  ProclamationForm (with category cascade), CategoryForm,
  FreqForm, LevelForm
- Update all admin +page.svelte files to use AdminTable + AdminModal
  + their specific form component instead of AdminPage
- Update profiles page to inline fields instead of using AdminForm
- Add custom Proclamation server action with category fallback logic
  (categoryId falls back to parentCategoryId when no sub-category)
- Remove cascade/were/fieldLabels logic from generic crud.ts
- Remove outdated cascade/where tests from crud.spec.ts
- Remove fieldLabels from AdminModelConfig type
2026-07-07 21:01:02 -05:00
NeilClack 2073248576 fix: Superforms SSR import from /server path and Prisma client version mismatch
- Import superValidate from sveltekit-superforms/server instead of default
  path to avoid pulling SuperDebug.svelte into SSR
- Upgrade @prisma/client to match prisma CLI version (7.2.0 -> 7.8.0)
  so generated client's query_compiler_fast_bg files exist at runtime
- Add regression test verifying superValidate works in server context
- Add regression test verifying generated Prisma client compiler imports
  reference real files
2026-07-07 13:39:11 -05:00
NeilClack 38d1752f5b admin: Superforms + Zod validation, three-address-defaults schema, profiles toast fix
- Add Superforms + Zod 4 for all admin form validation
- Replace address isDefault with three separate boolean defaults (Mailing, Billing, Shipping)
- Update profiles page with three-checkbox address form and toast improvements
- Convert all admin page server actions to pass request directly to crud
- Export superFormErrorsToFieldErrors helper for profiles server actions
- Regenerate Prisma client for new schema fields
2026-07-07 13:36:23 -05:00
NeilClack 38347f5f24 profiles: add address management, user edit, fix form redirect
- Add type (Mailing/Billing/Shipping) and isDefault fields to Address
  schema with migration. Unique default enforced server-side.
- Rewrite profiles page with inline address creation form and
  editable user name/email within the profile modal.
- Add upsertAddress and updateUser form actions.
- Fix form redirect by adding use:enhance to AdminForm.
- Disable Update button in AdminForm until a field is changed
  (prevents accidental submissions).
2026-07-07 13:20:35 -05:00
NeilClack faacbab1de admin: remove NavBar Admin Panel link, make users list-only
- Remove redundant Admin Panel link from top navigation bar. The
  sidebar already has the full admin model tree and the Dashboard
  shows a Proclamations card for Staff+ users.
- Add listOnly: true to users admin config. Users are created via
  registration, not the admin panel. RUD operations still work.
2026-07-07 13:07:34 -05:00
NeilClack 27aae18b3a refactor: inline single-use components, remove dead code
- Inline TopBar into root layout (+layout.svelte) — only used there
- Inline Center into home page (+page.svelte) — only used there
- Remove ComboBox.svelte — dead code, no imports
- Remove TipTap.svelte — dead code, no imports
- Remove empty container/ui/admin/tiptap directories
- Keep Window.svelte in components/containers/ — used by 4 pages
2026-07-07 10:40:59 -05:00
NeilClack b87e2b0936 fix: replace CSS variable inversion with standard Tailwind dark: classes
The :root.dark CSS variable inversion caused contrast problems -
text-gray-900 and bg-gray-950 both became light in dark mode, making
text invisible on backgrounds.

Fix:
- Remove :root.dark { --color-gray-*: ... } block from layout.css
- Change :root.dark selector to .dark for form element styles
- Add standard Tailwind dark: classes throughout every .svelte page
  - dark:bg-gray-950 (page backgrounds)
  - dark:bg-gray-900 (card/surface backgrounds)
  - dark:bg-gray-800 (table headers, elevated surfaces, active nav links)
  - dark:bg-gray-700 (primary buttons)
  - dark:text-gray-100 (primary text)
  - dark:text-gray-300 (secondary text, labels)
  - dark:text-gray-400 (muted text, inactive nav links, links)
  - dark:border-gray-700 (borders)
  - dark:border-gray-600 (input borders)
  - dark:hover:bg-gray-800 (sidebar hover)
  - dark:hover:bg-gray-600 (button hover)
  - dark:prose-invert (rich text content)
- TopBar: full dark mode support (bg, links, toggle button)
- Sidebar: all nav links, active states, admin submenu get dark mode
- Auth pages (login, register, forgot, reset): full dark mode
- Protected pages (dashboard, account, setup, license-keys,
  proclamations, categories): full dark mode
- Home page, error page, admin page: dark:text-gray-100
2026-07-07 10:27:08 -05:00
NeilClack 03ecfbd635 feat: add dark/light mode toggle
- Add blocking inline script in app.html that reads localStorage
  'theme' and applies .dark class before render (no flash)
- Invert gray scale in .dark via CSS custom properties so all
  grayscale colors reverse automatically (light becomes dark)
- Add @custom-variant dark to enable dark: utility classes
- Add border-button toggle ("Dark"/"Light") in TopBar far right
- Persist preference in localStorage
2026-07-07 09:54:32 -05:00
NeilClack 6ff8e878a4 test: add unit tests for all auth backend logic
- Register: edge cases for non-Error throws, error message assertions,
  and verify signUpEmail was called with correct payload
- Forgot-password: empty/missing email, Error/non-Error throws
- Reset-password: load (missing/expired/valid token) and action (short
  password, mismatch, throw, success redirect)
- Account setup: load (unauthorized, returns user), action (redirect,
  falsy create, throws, isRedirect passthrough)
- Email-verification: correct URL construction, sendMail delegation,
  throw propagation
- Hooks: sets/omits locals, passes building/auth to svelteKitHandler
- Fix Svelte 5  warning on setup page by using  with
  one-time guard instead of top-level prop read
2026-07-07 09:22:56 -05:00
NeilClack 209fd8456d auth: show email verified banner on login page after verification
- Append ?verified=true to callbackURL in verification link
- Login page reads query param and shows green success banner
  when user lands after email verification
2026-07-07 09:10:11 -05:00
NeilClack 667ae4e05e auth: build verification link from BASE_URL env var
- Build the verification URL as /api/auth/verify-email?token=xxx&callbackURL=/login
- Pass token from Better Auth callback instead of its built-in url
- Add callbackURL=/login so user lands on login after verifying
2026-07-07 08:59:25 -05:00