build: complete Phase 2.1 implementation and verify build

- Verified all exports in highlight-manager.ts are correct
- Installed @clerk/nextjs dependency for API routes
- Fixed TypeScript errors in API routes (NextRequest type)
- Fixed MUI Grid component usage in highlights-tab.tsx (replaced with Box flexbox)
- Fixed HighlightColor type assertion in reading-view.tsx
- Build completed successfully with no TypeScript errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-12 07:34:44 +00:00
parent b7b18c8d69
commit afaf580a2b
9 changed files with 205 additions and 13 deletions

View File

@@ -1,10 +1,10 @@
import { NextResponse } from 'next/server'
import { NextResponse, NextRequest } from 'next/server'
import { prisma } from '@/lib/db'
import { getAuth } from '@clerk/nextjs/server'
export const runtime = 'nodejs'
export async function GET(request: Request) {
export async function GET(request: NextRequest) {
try {
const { userId } = await getAuth(request)
if (!userId) {

View File

@@ -1,10 +1,10 @@
import { NextResponse } from 'next/server'
import { NextResponse, NextRequest } from 'next/server'
import { prisma } from '@/lib/db'
import { getAuth } from '@clerk/nextjs/server'
export const runtime = 'nodejs'
export async function POST(request: Request) {
export async function POST(request: NextRequest) {
try {
const { userId } = await getAuth(request)
if (!userId) {

View File

@@ -1,10 +1,10 @@
import { NextResponse } from 'next/server'
import { NextResponse, NextRequest } from 'next/server'
import { prisma } from '@/lib/db'
import { getAuth } from '@clerk/nextjs/server'
export const runtime = 'nodejs'
export async function POST(request: Request) {
export async function POST(request: NextRequest) {
try {
const { userId } = await getAuth(request)
if (!userId) {

View File

@@ -1,5 +1,5 @@
'use client'
import { Box, Button, Grid, Typography, Divider } from '@mui/material'
import { Box, Button, Typography, Divider } from '@mui/material'
import { BibleVerse, HighlightColor } from '@/types'
const HIGHLIGHT_COLORS: HighlightColor[] = ['yellow', 'orange', 'pink', 'blue']
@@ -55,9 +55,9 @@ export function HighlightsTab({
Highlight Color
</Typography>
<Grid container spacing={1} sx={{ mb: 2 }}>
<Box sx={{ display: 'flex', gap: 1, mb: 2 }}>
{HIGHLIGHT_COLORS.map((color) => (
<Grid item xs={3} key={color}>
<Box key={color} sx={{ flex: 1 }}>
<Button
data-testid={`color-${color}`}
fullWidth
@@ -74,9 +74,9 @@ export function HighlightsTab({
>
{color}
</Button>
</Grid>
</Box>
))}
</Grid>
</Box>
<Divider sx={{ my: 2 }} />

View File

@@ -137,7 +137,7 @@ export function ReadingView({
onMouseEnter={() => setHoveredVerseNum(verse.verseNum)}
onMouseLeave={() => setHoveredVerseNum(null)}
style={{
backgroundColor: (verse as any).highlight ? COLOR_MAP[(verse as any).highlight.color] : 'transparent',
backgroundColor: (verse as any).highlight ? COLOR_MAP[(verse as any).highlight.color as HighlightColor] : 'transparent',
padding: '0.25rem 0.5rem',
borderRadius: '4px',
cursor: 'pointer',

22
jest.config.js Normal file
View File

@@ -0,0 +1,22 @@
const nextJest = require('next/jest')
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})
// Add any custom config to be passed to Jest
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testEnvironment: 'jest-environment-jsdom',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1',
},
testMatch: [
'**/__tests__/**/*.test.ts',
'**/__tests__/**/*.test.tsx',
],
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)

169
package-lock.json generated
View File

@@ -9,6 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@clerk/nextjs": "^6.35.0",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@fontsource/roboto": "^5.2.8",
@@ -1406,6 +1407,112 @@
"url": "https://github.com/sponsors/Borewit"
}
},
"node_modules/@clerk/backend": {
"version": "2.21.0",
"resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-2.21.0.tgz",
"integrity": "sha512-L1SwcgVxpooE/UKla/ItVRQxPFHi7UxiH1ao5qnIWB0XC0ast6Xh6LvVpAeFZUo1SVMOvXairosJr+izxcp8Xw==",
"license": "MIT",
"dependencies": {
"@clerk/shared": "^3.33.0",
"@clerk/types": "^4.99.0",
"cookie": "1.0.2",
"standardwebhooks": "^1.0.0",
"tslib": "2.8.1"
},
"engines": {
"node": ">=18.17.0"
}
},
"node_modules/@clerk/backend/node_modules/cookie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@clerk/clerk-react": {
"version": "5.54.0",
"resolved": "https://registry.npmjs.org/@clerk/clerk-react/-/clerk-react-5.54.0.tgz",
"integrity": "sha512-3C+iwYWZKjnUvJ2X2JXuT4GjlPf/JlCICQ6VfGOrYKeLlTzKh9KmNJ7dKIGKETZxiNpn6JzttX70iBjH4sZ/1A==",
"license": "MIT",
"dependencies": {
"@clerk/shared": "^3.33.0",
"tslib": "2.8.1"
},
"engines": {
"node": ">=18.17.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0 || ^19.0.0-0",
"react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0"
}
},
"node_modules/@clerk/nextjs": {
"version": "6.35.0",
"resolved": "https://registry.npmjs.org/@clerk/nextjs/-/nextjs-6.35.0.tgz",
"integrity": "sha512-Iyofa0ZX6axoX1/cZkYcR8pigNKzLlpwSLKjjATZAQE1MCpaIJ4Chxt2a0QR9aEK0rcUjLD3G2+uq4A0cfaEYw==",
"license": "MIT",
"dependencies": {
"@clerk/backend": "^2.21.0",
"@clerk/clerk-react": "^5.54.0",
"@clerk/shared": "^3.33.0",
"@clerk/types": "^4.99.0",
"server-only": "0.0.1",
"tslib": "2.8.1"
},
"engines": {
"node": ">=18.17.0"
},
"peerDependencies": {
"next": "^13.5.7 || ^14.2.25 || ^15.2.3 || ^16",
"react": "^18.0.0 || ^19.0.0 || ^19.0.0-0",
"react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0"
}
},
"node_modules/@clerk/shared": {
"version": "3.33.0",
"resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-3.33.0.tgz",
"integrity": "sha512-llNbfNIkCz68H8N4jw4ogZbQaQdiIo3mg8rvR6IiClBwh0j53t2hVIQ685tuUhi5PAt+PQgZZw2Yct65hV35Cw==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"csstype": "3.1.3",
"dequal": "2.0.3",
"glob-to-regexp": "0.4.1",
"js-cookie": "3.0.5",
"std-env": "^3.9.0",
"swr": "2.3.4"
},
"engines": {
"node": ">=18.17.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0 || ^19.0.0-0",
"react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
},
"node_modules/@clerk/types": {
"version": "4.99.0",
"resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.99.0.tgz",
"integrity": "sha512-DggZfPGoW5e8jY1mYXRS34nFNnDISiBM00eqt3VHfcZb1+kgGUEBJo6HhULljUArB2Xq8OWeaOOPAhKC55Cp7A==",
"license": "MIT",
"dependencies": {
"@clerk/shared": "^3.33.0"
},
"engines": {
"node": ">=18.17.0"
}
},
"node_modules/@csstools/color-helpers": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
@@ -6661,6 +6768,12 @@
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
"license": "MIT"
},
"node_modules/@stablelib/base64": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz",
"integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==",
"license": "MIT"
},
"node_modules/@standard-schema/spec": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
@@ -9935,6 +10048,12 @@
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
"license": "MIT"
},
"node_modules/fast-sha256": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz",
"integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==",
"license": "Unlicense"
},
"node_modules/fast-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
@@ -10302,6 +10421,12 @@
"node": ">= 6"
}
},
"node_modules/glob-to-regexp": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
"license": "BSD-2-Clause"
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -12020,6 +12145,15 @@
"node": ">=10"
}
},
"node_modules/js-cookie": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -15641,6 +15775,12 @@
"node": ">=10"
}
},
"node_modules/server-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz",
"integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==",
"license": "MIT"
},
"node_modules/sharp": {
"version": "0.34.4",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz",
@@ -16055,12 +16195,28 @@
"node": ">=8"
}
},
"node_modules/standardwebhooks": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz",
"integrity": "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==",
"license": "MIT",
"dependencies": {
"@stablelib/base64": "^1.0.0",
"fast-sha256": "^1.3.0"
}
},
"node_modules/state-local": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
"license": "MIT"
},
"node_modules/std-env": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
"integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
"license": "MIT"
},
"node_modules/streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
@@ -16374,6 +16530,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/swr": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/swr/-/swr-2.3.4.tgz",
"integrity": "sha512-bYd2lrhc+VarcpkgWclcUi92wYCpOgMws9Sd1hG1ntAu0NEy+14CbotuFjshBU2kt9rYj9TSmDcybpxpeTU1fg==",
"license": "MIT",
"dependencies": {
"dequal": "^2.0.3",
"use-sync-external-store": "^1.4.0"
},
"peerDependencies": {
"react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/symbol-tree": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",

View File

@@ -24,6 +24,7 @@
"license": "ISC",
"description": "",
"dependencies": {
"@clerk/nextjs": "^6.35.0",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@fontsource/roboto": "^5.2.8",

File diff suppressed because one or more lines are too long