Skip to content
This repository was archived by the owner on Nov 23, 2025. It is now read-only.

Commit cd985e1

Browse files
authored
Merge pull request #37 from TechTorque-2025/dev
Dev
2 parents fba1755 + 2e11791 commit cd985e1

63 files changed

Lines changed: 1985 additions & 965 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,26 @@ This repository contains the source code for the TechTorque 2025 customer and em
4848
npm run setup-hooks
4949
```
5050
This configures automatic linting on commit and build checking on push. See [GIT_HOOKS.md](GIT_HOOKS.md) for details.
51+
52+
### 🔌 Environment
53+
54+
- The frontend expects an API base to be available at runtime. You can configure this via the
55+
`NEXT_PUBLIC_API_BASE_URL` environment variable. When not set, the runtime defaults to
56+
`http://localhost:8080` (useful in development).
57+
58+
- The AI chat widget reaches the AI chat proxy at `/api/v1/ai/chat` (or `{{NEXT_PUBLIC_API_BASE_URL}}/api/v1/ai/chat` when the public API base is set). This ensures the frontend talks to the configured API gateway or the local Next.js proxy.
59+
60+
### 🎨 Theme & Styling (Centralized)
61+
62+
- A single global stylesheet lives at `src/app/globals.css` and contains all theme variables for light & dark mode, plus utility classes like:
63+
- `.theme-button-primary`, `.theme-button-secondary` — semantic buttons
64+
- `.theme-bg-primary`, `.theme-text-primary`, `.theme-border`, etc — consistent building blocks
65+
- `.automotive-accent`, `.accent-badge`, `.text-gradient-accent`, `.progress-accent` — accent utilities
66+
67+
- Theme switching is implemented using `src/app/contexts/ThemeContext.tsx` plus a small pre-hydration script in `src/app/layout.tsx` (so the app applies the saved system preference or previously saved theme before React mounts to avoid flashes).
68+
69+
- Quick checks added:
70+
- `npm run check:theme` — verifies `globals.css` and `ThemeContext` contain expected hooks and variables.
71+
- `npm run check:colors` — scans `src/` for hardcoded hex/rgb color usage (ignores `globals.css`).
72+
73+
If you're adding new UI colors, add variables to `src/app/globals.css` and use the semantic utility classes (or create new ones) — this keeps light/dark behavior centralized and consistent across the app.

package-lock.json

Lines changed: 40 additions & 40 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
"build": "next build --turbopack",
88
"start": "next start",
99
"lint": "eslint",
10+
"check:colors": "node ./scripts/check-hardcoded-colors.js",
11+
"check:theme": "node ./scripts/check-theme-setup.js",
1012
"setup-hooks": "chmod +x .githooks/pre-commit .githooks/pre-push && git config core.hooksPath .githooks && echo '✅ Git hooks configured successfully!'"
1113
},
1214
"dependencies": {
1315
"@stomp/stompjs": "^7.2.1",
1416
"axios": "^1.12.2",
1517
"js-cookie": "^3.0.5",
1618
"lucide-react": "^0.553.0",
17-
"next": "^16.0.1",
19+
"next": "^16.0.3",
1820
"react": "19.1.0",
1921
"react-dom": "19.1.0",
2022
"sockjs-client": "^1.6.1"

scripts/check-hardcoded-colors.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env node
2+
import fs from 'fs'
3+
import path from 'path'
4+
5+
const root = path.resolve(__dirname, '..', 'src')
6+
7+
const hexRe = /#[0-9a-fA-F]{3,6}/g
8+
const rgbRe = /rgba?\(/gi
9+
10+
function walk(dir) {
11+
const entries = fs.readdirSync(dir, { withFileTypes: true })
12+
for (const e of entries) {
13+
const full = path.join(dir, e.name)
14+
if (e.isDirectory()) {
15+
walk(full)
16+
} else if (e.isFile()) {
17+
if (full.endsWith('globals.css')) continue
18+
if (!full.endsWith('.css') && !full.endsWith('.tsx') && !full.endsWith('.ts') && !full.endsWith('.jsx') && !full.endsWith('.js') && !full.endsWith('.svg')) continue
19+
const content = fs.readFileSync(full, 'utf8')
20+
const hex = content.match(hexRe)
21+
const rgb = content.match(rgbRe)
22+
if ((hex && hex.length) || (rgb && rgb.length)) {
23+
console.log(`Found in ${path.relative(process.cwd(), full)} -> hex:${hex ? hex.join(',') : '0'} rgb:${rgb ? rgb.length : 0}`)
24+
}
25+
}
26+
}
27+
}
28+
29+
try {
30+
walk(root)
31+
console.log('\nSearch complete — open the above files and replace hardcoded colors with theme variables in src/app/globals.css.')
32+
} catch (err) {
33+
console.error(err)
34+
process.exit(1)
35+
}

scripts/check-theme-setup.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env node
2+
import fs from 'fs'
3+
import path from 'path'
4+
5+
const globals = fs.readFileSync(path.resolve(__dirname, '../src/app/globals.css'), 'utf8')
6+
const themeContext = fs.readFileSync(path.resolve(__dirname, '../src/app/contexts/ThemeContext.tsx'), 'utf8')
7+
8+
let ok = true
9+
10+
function assert(cond, msg) {
11+
if (!cond) {
12+
console.error('FAIL:', msg)
13+
ok = false
14+
} else {
15+
console.log('OK:', msg)
16+
}
17+
}
18+
19+
assert(globals.includes(':root'), 'globals.css has :root declarations')
20+
assert(globals.includes('html.dark'), 'globals.css has html.dark overrides')
21+
assert(globals.includes('--accent-primary'), 'globals.css defines --accent-primary var')
22+
23+
assert(themeContext.includes("localStorage.getItem('theme')"), 'ThemeContext reads localStorage')
24+
assert(themeContext.includes("document.documentElement.classList"), 'ThemeContext manipulates document.documentElement classList')
25+
26+
if (!ok) process.exit(1)
27+
console.log('\nTheme setup basic checks passed — globals.css + ThemeContext look correctly configured.')

src/app/admin/page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export default function AdminDashboard() {
9494
<div className="flex gap-4">
9595
<button
9696
onClick={() => router.push("/profile")}
97-
className="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors"
97+
className="px-4 py-2 theme-button-primary rounded-lg transition-colors"
9898
>
9999
My Profile
100100
</button>
@@ -108,13 +108,13 @@ export default function AdminDashboard() {
108108
</div>
109109

110110
{error && (
111-
<div className="mb-6 p-4 bg-red-50 dark:bg-red-900/20 rounded-lg border border-red-200 dark:border-red-800">
112-
<p className="text-sm text-red-600 dark:text-red-400">{error}</p>
111+
<div className="mb-6 theme-alert-danger">
112+
<p className="text-sm">{error}</p>
113113
</div>
114114
)}
115115

116116
{success && (
117-
<div className="mb-6 p-4 bg-green-50 dark:bg-green-900/20 rounded-lg border border-green-200 dark:border-green-800">
117+
<div className="mb-6 theme-alert-success">
118118
<p className="text-sm text-green-600 dark:text-green-400">
119119
{success}
120120
</p>

src/app/auth/forgot-password/page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import Link from 'next/link'
66
import authService from '../../../services/authService'
77
import ThemeToggle from '../../components/ThemeToggle'
88

9-
const Icon = ({ d, size = 10 }: { d: string; size?: number }) => ( <svg className={`w-${size} h-${size} text-white`} fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={d} /></svg>);
10-
const BoltIcon = ({size = 10}) => <Icon d="M13 10V3L4 14h7v7l9-11h-7z" size={size} />;
9+
// (removed unused Icon helper)
10+
1111

1212
// --- Forgot Password Page Component ---
1313
export default function ForgotPasswordPage() {
@@ -46,7 +46,7 @@ export default function ForgotPasswordPage() {
4646
<header className="sticky-header shadow-lg border-b theme-border">
4747
<div className="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8">
4848
<div className="flex justify-between items-center">
49-
<Link href="/" className="flex items-center space-x-3 group"><div className="w-12 h-12 rounded-full bg-gradient-to-r from-blue-500 to-cyan-400 flex items-center justify-center shadow-lg transform transition-transform duration-300 group-hover:scale-110"><BoltIcon size={6} /></div><h1 className="text-2xl font-bold theme-text-primary hidden sm:block">TechTorque Auto</h1></Link>
49+
<Link href="/" className="flex items-center space-x-3 group"><div className="automotive-accent w-12 h-12 rounded-full flex items-center justify-center shadow-lg transform transition-transform duration-300 group-hover:scale-110"><span className="text-white font-bold text-lg">TT</span></div><h1 className="text-2xl font-bold theme-text-primary hidden sm:block">TechTorque</h1></Link>
5050
<div className="flex items-center space-x-4"><Link href="/auth/login" className="theme-link hidden md:inline-block">Back to Sign In</Link><ThemeToggle /></div>
5151
</div>
5252
</div>
@@ -74,7 +74,7 @@ export default function ForgotPasswordPage() {
7474
</div>
7575
{error && (
7676
<div className="mb-6 p-4 bg-red-50 dark:bg-red-900/20 rounded-lg border border-red-200 dark:border-red-800">
77-
<p className="text-sm text-red-600 dark:text-red-400">{error}</p>
77+
<p className="text-sm theme-text-danger">{error}</p>
7878
</div>
7979
)}
8080
<form className="space-y-6" onSubmit={handleSubmit}>

src/app/auth/login/page.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,8 @@ import authService from '../../../services/authService';
88
import type { LoginRequest } from '../../../types/api';
99
import ThemeToggle from '../../components/ThemeToggle';
1010

11-
// Icon Components
12-
const Icon = ({ d, size = 10 }: { d: string; size?: number }) => (
13-
<svg className={`w-${size} h-${size} text-white`} fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
14-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={d} />
15-
</svg>
16-
);
17-
const BoltIcon = ({size = 10}) => <Icon d="M13 10V3L4 14h7v7l9-11h-7z" size={size} />;
11+
// (removed unused Icon helper)
12+
1813
const LockClosedIcon = () => <svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" /></svg>;
1914

2015

@@ -74,11 +69,11 @@ export default function LoginPage() {
7469
<div className="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8">
7570
<div className="flex justify-between items-center">
7671
<Link href="/" className="flex items-center space-x-3 group">
77-
<div className="w-12 h-12 rounded-full bg-gradient-to-r from-blue-500 to-cyan-400 flex items-center justify-center shadow-lg transform transition-transform duration-300 group-hover:scale-110">
78-
<BoltIcon size={6} />
72+
<div className="automotive-accent w-12 h-12 rounded-full flex items-center justify-center shadow-lg transform transition-transform duration-300 group-hover:scale-110">
73+
<span className="text-white font-bold text-lg">TT</span>
7974
</div>
8075
<h1 className="text-2xl font-bold theme-text-primary hidden sm:block">
81-
TechTorque Auto
76+
TechTorque
8277
</h1>
8378
</Link>
8479
<div className="flex items-center space-x-4">
@@ -152,7 +147,7 @@ export default function LoginPage() {
152147
</form>
153148
{error && (
154149
<div role="alert" className="mt-4 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg">
155-
<p className="text-sm text-red-600 dark:text-red-400 mb-2">{error}</p>
150+
<p className="text-sm theme-text-danger mb-2">{error}</p>
156151
{unverifiedEmail && (
157152
<Link
158153
href={`/auth/resend-verification?email=${encodeURIComponent(unverifiedEmail)}`}

0 commit comments

Comments
 (0)