Commit Graph

11 Commits

Author SHA1 Message Date
Chandler Copeland
c1e1e5ec49 feat(13-01): implement aiCoordsToPagePdfSpace and AI field utilities
- Install openai 6.32.0 (npm package, listed in dependencies)
- Create src/lib/ai/extract-text.ts — pdfjs-dist legacy build server-side text extraction
  - extractPdfText(filePath) returning PageText[] with page, text, width, height
  - GlobalWorkerOptions.workerSrc = '' for Node.js fake-worker mode
  - Text per page capped at 2000 chars for GPT-4o-mini context limit
- Create src/lib/ai/field-placement.ts — GPT-4o-mini structured output + coord conversion
  - aiCoordsToPagePdfSpace() converts AI top-left pct coords to PDF bottom-left points
  - classifyFieldsWithAI() uses manual json_schema (NOT zodResponseFormat — broken with Zod v4)
  - Standard field sizes: checkbox=24x24pt, others=144x36pt
  - textFillData keyed by field UUID (not label) per Phase 12.1 design
- All 3 unit tests pass (GREEN phase confirmed)
2026-03-21 17:00:34 -06:00
Chandler Copeland
fa68a1bcb4 feat(06-01): install packages + extend schema + generate migration
- installed signature_pad, @react-email/render, @react-email/components
- added signingTokens table (jti pk, documentId, expiresAt, usedAt)
- added auditEvents table with auditEventTypeEnum (6 event types)
- added signedFilePath, pdfHash, signedAt columns to documents table
- generated and applied migration 0005_signing_flow.sql
2026-03-20 11:24:02 -06:00
Chandler Copeland
6069ae5e06 feat(05-02): install dnd-kit and create FieldPlacer component
- Install @dnd-kit/core@^6.3.1 and @dnd-kit/utilities@^3.2.2
- Create FieldPlacer.tsx with DndContext, draggable palette token, droppable PDF zone
- Implements Y-flip coordinate conversion (screenToPdfCoords / pdfToScreenCoords)
- Fetches existing fields from GET /api/documents/[id]/fields on mount
- Persists fields via PUT /api/documents/[id]/fields on every add/remove
- Renders placed fields as absolute-positioned blue-bordered overlays with remove button
- Default field size: 144x36 PDF points (2in x 0.5in at 72 DPI)
2026-03-19 23:59:51 -06:00
Chandler Copeland
34ed0baa43 test(05-01): add unit tests for Y-flip coordinate conversion formula
- Created src/lib/pdf/__tests__/prepare-document.test.ts with 10 test cases
- Tests verify Y-axis flip: screenY=0 → pdfY≈792, screenY=792 → pdfY≈0
- Tests verify scale-invariance at both 1:1 and 50% zoom ratios
- Installed jest, ts-jest, @types/jest and added jest config to package.json
- All 10 tests pass

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 23:55:27 -06:00
Chandler Copeland
c81e8ea838 feat(05-01): add preparePdf utility and fields/prepare API routes
- Installed @cantoo/pdf-lib for server-side PDF mutation
- Created src/lib/pdf/prepare-document.ts with preparePdf function using atomic tmp->rename write pattern
- form.flatten() called before drawing signature rectangles
- Created GET/PUT /api/documents/[id]/fields routes for signature field storage
- Created POST /api/documents/[id]/prepare route that calls preparePdf and transitions status to Sent
- Fixed pre-existing null check error in scripts/debug-inspect2.ts (Rule 3: blocking build)
- Build compiles successfully with 2 new API routes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 23:54:41 -06:00
Chandler Copeland
27462a0ebb feat: add Playwright script to scrape SkySlope form libraries into seeds/forms/ 2026-03-19 22:27:41 -06:00
Chandler Copeland
63e5888968 feat(04-03): install react-pdf and configure Next.js transpilePackages
- npm install react-pdf (v9+ pulls in pdfjs-dist automatically)
- Add transpilePackages: ['react-pdf', 'pdfjs-dist'] to next.config.ts
- Build verified passing after config change
2026-03-19 21:42:06 -06:00
Chandler Copeland
f82364d2c7 feat(04-01): create seed-forms script and npm run seed:forms command
- Create scripts/seed-forms.ts: reads seeds/forms/, upserts PDFs into form_templates via onConflictDoUpdate on filename
- Add seed:forms script to package.json with DOTENV_CONFIG_PATH=.env.local prefix
- Empty seeds/forms/ prints guidance message and exits 0 (monthly-sync workflow ready)
2026-03-19 21:33:02 -06:00
Chandler Copeland
39f233dbb4 feat(02-02): install nodemailer and create contact mailer + server action
- Add nodemailer@^7.0.7 and @types/nodemailer (v7 required by next-auth peer dep)
- Create src/lib/contact-mailer.ts: Nodemailer SMTP transporter + sendContactEmail()
- Create src/lib/contact-action.ts: Server Action with Zod validation, honeypot check
- SMTP credentials read from CONTACT_EMAIL_USER/PASS/SMTP_HOST/PORT env vars
- Add CONTACT_* placeholder vars to .env.local (gitignored, for local setup docs)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 14:59:23 -06:00
Chandler Copeland
0a75442af3 fix(db): swap @neondatabase/serverless for postgres.js (local dev support)
Neon serverless driver requires remote WebSocket — incompatible with local
PostgreSQL. Replaced with postgres.js (drizzle-orm/postgres-js) in db/index.ts,
scripts/seed.ts, and drizzle.config.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 14:00:32 -06:00
Chandler Copeland
dac1bc817b feat(01-01): scaffold Next.js 16.2.0 project with all Phase 1 dependencies
- Created teressa-copeland-homes with TypeScript, Tailwind, ESLint, App Router, src dir
- Installed next-auth@5.0.0-beta.30 (pinned exact version), drizzle-orm, @neondatabase/serverless
- Installed bcryptjs, @vercel/blob, zod, drizzle-kit, tsx, dotenv
- Added db:generate, db:migrate, db:seed, db:studio npm scripts
- Verified npm run build passes with zero TypeScript errors
2026-03-19 13:29:56 -06:00