From e1247ce1b22c5569b383aead84403252ac953efb Mon Sep 17 00:00:00 2001 From: sriram Date: Tue, 25 Aug 2026 11:06:54 +0530 Subject: [PATCH] Login page Authenticate and input icon --- .env.unified | 21 +++++++++++++++++++++ README.md | 18 +++++++++++++++++- package.json | 1 + src/pages/LoginPage.jsx | 29 ++++++++++++++++++++++++++--- vite.config.js | 28 +++++++++++++++++++--------- 5 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 .env.unified diff --git a/.env.unified b/.env.unified new file mode 100644 index 0000000..a20587b --- /dev/null +++ b/.env.unified @@ -0,0 +1,21 @@ +# Build profile for a bundle that is served by the FastAPI backend itself. +# +# Use it with: npm run build:unified +# +# Why this file exists: `npm run build` loads .env.production, which pins +# VITE_API_BASE_URL to https://mcp.nearle.ai.in. That is correct for the +# deployed site (served from catalogue.nearle.ai.in, calling the API on its +# own subdomain) but wrong for every local build, because backend/app/main.py +# serves frontend/dist automatically whenever it exists. Opening +# http://localhost:8000 then loads a bundle that sends /api/auth/login to the +# remote host instead of the backend sitting on the same port - so logging in +# with the local admin credentials fails with "Could not reach the API", +# which reads like the backend being down when it is running fine. +# +# Blank means requests stay relative ("/api/..."), i.e. same-origin, so they +# land on whichever server delivered the page. That is exactly what the +# single-port unified deployment needs, and it needs no CORS entry at all. +# +# Same value and same reasoning as .env.development; separate file because +# Vite only loads .env.development in dev mode, never during a build. +VITE_API_BASE_URL= diff --git a/README.md b/README.md index 65f5a53..a169ee2 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,26 @@ If your backend runs somewhere else, set `VITE_API_BASE_URL` in a local ## Production build ```bash -npm run build # outputs to dist/ +npm run build # outputs to dist/ - for the DEPLOYED site only npm run preview # serve the production build locally to sanity-check it ``` +`npm run build` loads `.env.production`, which pins `VITE_API_BASE_URL` to +`https://mcp.nearle.ai.in`. That is right for the deployed site and wrong for +anything you run locally, because the backend serves `frontend/dist` itself +whenever that directory exists - so `http://localhost:8000` would hand you a +page that sends `/api/auth/login` to the remote host and fails with "Could not +reach the API" even though the local backend is up. For a build you intend to +run locally, use: + +```bash +npm run build:unified # same optimised build, blank VITE_API_BASE_URL +``` + +That leaves API calls relative, so they go back to whichever server delivered +the page - port 8000 for the backend's single-port mode, or `npm run preview`, +which proxies `/api/*` to `127.0.0.1:8000` the same way the dev server does. + ## Pages - `/` - Browse & Search (sidebar brand/category filters, product grid, diff --git a/package.json b/package.json index 0ab8323..27e4e04 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "dev": "vite", "build": "vite build", + "build:unified": "vite build --mode unified", "lint": "oxlint", "preview": "vite preview" }, diff --git a/src/pages/LoginPage.jsx b/src/pages/LoginPage.jsx index c4a988f..06f71a3 100644 --- a/src/pages/LoginPage.jsx +++ b/src/pages/LoginPage.jsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAuth } from '../context/useAuth'; -import { ShieldCheck, Lock, User, ArrowRight, Sparkles } from 'lucide-react'; +import { ShieldCheck, Lock, User, ArrowRight, Sparkles, Eye, EyeOff } from 'lucide-react'; /* * There is exactly one interactive account: `admin`. @@ -19,6 +19,7 @@ export function LoginPage() { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); + const [showPassword, setShowPassword] = useState(false); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); @@ -96,14 +97,36 @@ export function LoginPage() {
+ {/* pr-11, unlike the username field's pr-4, keeps a long + password from running underneath the toggle button. */} setPassword(e.target.value)} placeholder="Enter password" - className="w-full rounded-xl border border-ink-900/15 bg-white py-2.5 pl-9 pr-4 text-sm text-ink-950 placeholder-slate-400 focus:border-amber-500 focus:outline-none focus:ring-2 focus:ring-amber-500/25" + className="w-full rounded-xl border border-ink-900/15 bg-white py-2.5 pl-9 pr-11 text-sm text-ink-950 placeholder-slate-400 focus:border-amber-500 focus:outline-none focus:ring-2 focus:ring-amber-500/25" /> + {/* + type="button" is load-bearing: a
diff --git a/vite.config.js b/vite.config.js index 9385678..535791e 100644 --- a/vite.config.js +++ b/vite.config.js @@ -2,19 +2,29 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' +// Both dev and preview forward /api/* to FastAPI, so a same-origin (relative) +// request works whichever local server is delivering the page. Keep the two in +// sync: `preview` serves dist/, and without this it would answer /api with a +// 404 index.html, which surfaces in the UI as a login failure. +const apiProxy = { + '/api': { + // Proxy all /api/* requests straight to FastAPI on port 8000 + target: 'http://127.0.0.1:8000', + changeOrigin: true, + secure: false, + ws: true, + }, +} + // https://vite.dev/config/ export default defineConfig({ plugins: [react(), tailwindcss()], server: { port: 5173, - proxy: { - // Proxy all /api/* requests straight to FastAPI on port 8000 - '/api': { - target: 'http://127.0.0.1:8000', - changeOrigin: true, - secure: false, - ws: true, - }, - }, + proxy: apiProxy, + }, + preview: { + port: 4173, + proxy: apiProxy, }, })