Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export default tseslint.config(
'warn',
{ allowConstantExport: true },
],
quotes: ['error', 'double'],
semi: ['error', 'always'],
},
},
)
24 changes: 12 additions & 12 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Navigation from './components/Navigation';
import Welcome from './components/Welcome';
import About from './components/About';
import Footer from './components/Footer';
import Products from './components/entity/product/Products';
import Login from './components/Login';
import { AuthProvider } from './context/AuthContext';
import { ThemeProvider } from './context/ThemeContext';
import AdminProducts from './components/admin/AdminProducts';
import { useTheme } from './context/ThemeContext';
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Navigation from "./components/Navigation";
import Welcome from "./components/Welcome";
import About from "./components/About";
import Footer from "./components/Footer";
import Products from "./components/entity/product/Products";
import Login from "./components/Login";
import { AuthProvider } from "./context/AuthContext";
import { ThemeProvider } from "./context/ThemeContext";
import AdminProducts from "./components/admin/AdminProducts";
import { useTheme } from "./context/ThemeContext";

// Wrapper component to apply theme classes
function ThemedApp() {
const { darkMode } = useTheme();

return (
<Router>
<div className={`flex flex-col min-h-screen ${darkMode ? 'bg-dark' : 'bg-gray-100'} transition-colors duration-300`}>
<div className={`flex flex-col min-h-screen ${darkMode ? "bg-dark" : "bg-gray-100"} transition-colors duration-300`}>
<Navigation />
<main className="flex-grow">
<Routes>
Expand Down
28 changes: 14 additions & 14 deletions frontend/src/api/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ declare global {

const getBaseUrl = () => {
// First check runtime configuration (from runtime-config.js)
if (typeof window !== 'undefined' && window.RUNTIME_CONFIG?.API_URL) {
console.log('Using runtime config API_URL:', window.RUNTIME_CONFIG.API_URL);
if (typeof window !== "undefined" && window.RUNTIME_CONFIG?.API_URL) {
console.log("Using runtime config API_URL:", window.RUNTIME_CONFIG.API_URL);
return window.RUNTIME_CONFIG.API_URL;
}

// Check if we're in a Codespace
const codespaceName = process.env.CODESPACE_NAME;
if (codespaceName) {
// Use the same protocol as the current page
const protocol = typeof window !== 'undefined' ? window.location.protocol : 'https:';
const protocolToUse = protocol.includes('https') ? 'https' : 'http';
const protocol = typeof window !== "undefined" ? window.location.protocol : "https:";
const protocolToUse = protocol.includes("https") ? "https" : "http";
console.log(`Using Codespace URL with ${protocolToUse} protocol`);
return `${protocolToUse}://${codespaceName}-3000.app.github.dev`;
}

// Auto-detect protocol for local development
const protocol = typeof window !== 'undefined' ? window.location.protocol : 'http:';
const protocolToUse = protocol.includes('https') ? 'https' : 'http';
const protocol = typeof window !== "undefined" ? window.location.protocol : "http:";
const protocolToUse = protocol.includes("https") ? "https" : "http";
console.log(`Using default localhost URL with ${protocolToUse} protocol`);
return `${protocolToUse}://localhost:3000`;
};
Expand All @@ -36,13 +36,13 @@ export const API_BASE_URL = getBaseUrl();
export const api = {
baseURL: API_BASE_URL,
endpoints: {
products: '/api/products',
suppliers: '/api/suppliers',
orders: '/api/orders',
branches: '/api/branches',
headquarters: '/api/headquarters',
deliveries: '/api/deliveries',
orderDetails: '/api/order-details',
orderDetailDeliveries: '/api/order-detail-deliveries'
products: "/api/products",
suppliers: "/api/suppliers",
orders: "/api/orders",
branches: "/api/branches",
headquarters: "/api/headquarters",
deliveries: "/api/deliveries",
orderDetails: "/api/order-details",
orderDetailDeliveries: "/api/order-detail-deliveries"
}
};
10 changes: 5 additions & 5 deletions frontend/src/components/About.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useTheme } from '../context/ThemeContext';
import { useTheme } from "../context/ThemeContext";

const About = () => {
const { darkMode } = useTheme();

return (
<div className={`min-h-screen flex flex-col items-center justify-center ${darkMode ? 'bg-dark' : 'bg-gray-100'} p-4 transition-colors duration-300`}>
<div className={`max-w-4xl w-full ${darkMode ? 'bg-gray-800 text-gray-300' : 'bg-white text-gray-700'} rounded-lg shadow-lg p-8 border ${darkMode ? 'border-primary/20' : 'border-gray-200'} transition-colors duration-300`}>
<h1 className={`text-4xl font-bold mb-8 ${darkMode ? 'text-white' : 'text-gray-800'} transition-colors duration-300`}>About OctoCAT Supply</h1>
<div className={`min-h-screen flex flex-col items-center justify-center ${darkMode ? "bg-dark" : "bg-gray-100"} p-4 transition-colors duration-300`}>
<div className={`max-w-4xl w-full ${darkMode ? "bg-gray-800 text-gray-300" : "bg-white text-gray-700"} rounded-lg shadow-lg p-8 border ${darkMode ? "border-primary/20" : "border-gray-200"} transition-colors duration-300`}>
<h1 className={`text-4xl font-bold mb-8 ${darkMode ? "text-white" : "text-gray-800"} transition-colors duration-300`}>About OctoCAT Supply</h1>
<div className="space-y-6">
<p>
Welcome to OctoCAT Supply, your premier destination for AI-powered smart products
Expand Down Expand Up @@ -36,7 +36,7 @@ const About = () => {
<li>Energy-efficient and eco-friendly materials</li>
<li>Sleek, modern designs that complement your home</li>
</ul>
<div className={`mt-8 p-4 ${darkMode ? 'bg-gray-700' : 'bg-gray-200'} rounded-lg transition-colors duration-300`}>
<div className={`mt-8 p-4 ${darkMode ? "bg-gray-700" : "bg-gray-200"} rounded-lg transition-colors duration-300`}>
<p className="italic">
"Our cats tested every product in our catalog extensively. Only the ones they
couldn't stop using made it to production." — Felix Whiskerton, Founder
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import { useTheme } from '../context/ThemeContext';
import React from "react";
import { useTheme } from "../context/ThemeContext";

const Footer: React.FC = () => {
const { darkMode } = useTheme();

return (
<footer className={`${darkMode ? 'bg-gray-900 text-gray-300' : 'bg-gray-200 text-gray-700'} py-8 transition-colors duration-300`}>
<footer className={`${darkMode ? "bg-gray-900 text-gray-300" : "bg-gray-200 text-gray-700"} py-8 transition-colors duration-300`}>
<div className="container mx-auto px-4">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
{/* About Section */}
Expand Down Expand Up @@ -53,7 +53,7 @@ const Footer: React.FC = () => {
</div>
</div>

<div className={`mt-8 pt-8 ${darkMode ? 'border-gray-700' : 'border-gray-300'} border-t text-center text-sm transition-colors duration-300`}>
<div className={`mt-8 pt-8 ${darkMode ? "border-gray-700" : "border-gray-300"} border-t text-center text-sm transition-colors duration-300`}>
<p>Copyright © 2025 OctoCAT Supply. All Rights Reserved</p>
</div>
</div>
Expand Down
34 changes: 17 additions & 17 deletions frontend/src/components/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { useState, useEffect } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import { useTheme } from '../context/ThemeContext';
import { useState, useEffect } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
import { useTheme } from "../context/ThemeContext";

export default function Login() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const navigate = useNavigate();
const { login } = useAuth();
const { darkMode } = useTheme();
const [searchParams] = useSearchParams();

useEffect(() => {
const errorMsg = searchParams.get('error');
const errorMsg = searchParams.get("error");
if (errorMsg) {
setError(errorMsg);
}
Expand All @@ -23,16 +23,16 @@ export default function Login() {
e.preventDefault();
try {
await login(email, password);
navigate('/');
navigate("/");
} catch {
setError('Login failed. Please try again.');
setError("Login failed. Please try again.");
}
};

return (
<div className={`min-h-screen pt-20 ${darkMode ? 'bg-dark' : 'bg-gray-100'} flex items-center justify-center px-4 transition-colors duration-300`}>
<div className={`max-w-md w-full ${darkMode ? 'bg-gray-800' : 'bg-white'} rounded-lg shadow-lg p-8 transition-colors duration-300`}>
<h2 className={`text-3xl font-bold ${darkMode ? 'text-light' : 'text-gray-800'} mb-6 transition-colors duration-300`}>Login</h2>
<div className={`min-h-screen pt-20 ${darkMode ? "bg-dark" : "bg-gray-100"} flex items-center justify-center px-4 transition-colors duration-300`}>
<div className={`max-w-md w-full ${darkMode ? "bg-gray-800" : "bg-white"} rounded-lg shadow-lg p-8 transition-colors duration-300`}>
<h2 className={`text-3xl font-bold ${darkMode ? "text-light" : "text-gray-800"} mb-6 transition-colors duration-300`}>Login</h2>

{error && (
<div
Expand All @@ -43,26 +43,26 @@ export default function Login() {

<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="email" className={`block ${darkMode ? 'text-light' : 'text-gray-700'} mb-2 transition-colors duration-300`}>Email Address</label>
<label htmlFor="email" className={`block ${darkMode ? "text-light" : "text-gray-700"} mb-2 transition-colors duration-300`}>Email Address</label>
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className={`w-full ${darkMode ? 'bg-gray-700 text-light' : 'bg-gray-100 text-gray-800'} rounded px-3 py-2 transition-colors duration-300`}
className={`w-full ${darkMode ? "bg-gray-700 text-light" : "bg-gray-100 text-gray-800"} rounded px-3 py-2 transition-colors duration-300`}
required
autoFocus
/>
</div>

<div>
<label htmlFor="password" className={`block ${darkMode ? 'text-light' : 'text-gray-700'} mb-2 transition-colors duration-300`}>Password</label>
<label htmlFor="password" className={`block ${darkMode ? "text-light" : "text-gray-700"} mb-2 transition-colors duration-300`}>Password</label>
<input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className={`w-full ${darkMode ? 'bg-gray-700 text-light' : 'bg-gray-100 text-gray-800'} rounded px-3 py-2 transition-colors duration-300`}
className={`w-full ${darkMode ? "bg-gray-700 text-light" : "bg-gray-100 text-gray-800"} rounded px-3 py-2 transition-colors duration-300`}
required
/>
</div>
Expand Down
30 changes: 15 additions & 15 deletions frontend/src/components/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Link } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import { useTheme } from '../context/ThemeContext';
import { useState } from 'react';
import { Link } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
import { useTheme } from "../context/ThemeContext";
import { useState } from "react";

export default function Navigation() {
const { isLoggedIn, isAdmin, logout } = useAuth();
const { darkMode, toggleTheme } = useTheme();
const [adminMenuOpen, setAdminMenuOpen] = useState(false);

return (
<nav className={`${darkMode ? 'bg-dark/95' : 'bg-white/95'} backdrop-blur-sm fixed w-full z-50 shadow-md transition-colors duration-300`}>
<nav className={`${darkMode ? "bg-dark/95" : "bg-white/95"} backdrop-blur-sm fixed w-full z-50 shadow-md transition-colors duration-300`}>
<div className="max-w-7xl mx-auto px-4">
<div className="flex items-center justify-between h-16">
<div className="flex-shrink-0 flex items-center">
Expand All @@ -20,25 +20,25 @@ export default function Navigation() {
className="h-8 w-auto"
/>
<div className="ml-2">
<span className={`text-xl font-bold ${darkMode ? 'text-light' : 'text-gray-800'}`}>OctoCAT Supply</span>
<span className={`text-xl font-bold ${darkMode ? "text-light" : "text-gray-800"}`}>OctoCAT Supply</span>
<span className="block text-xs text-primary">Smart Cat Tech, Powered by AI</span>
</div>
</Link>
</div>
<div className="hidden md:block">
<div className="ml-10 flex items-baseline space-x-4">
<Link to="/" className={`${darkMode ? 'text-light hover:text-primary' : 'text-gray-700 hover:text-primary'} px-3 py-2 rounded-md text-sm font-medium transition-colors`}>Home</Link>
<Link to="/products" className={`${darkMode ? 'text-light hover:text-primary' : 'text-gray-700 hover:text-primary'} px-3 py-2 rounded-md text-sm font-medium transition-colors`}>Products</Link>
<Link to="/about" className={`${darkMode ? 'text-light hover:text-primary' : 'text-gray-700 hover:text-primary'} px-3 py-2 rounded-md text-sm font-medium transition-colors`}>About us</Link>
<Link to="/" className={`${darkMode ? "text-light hover:text-primary" : "text-gray-700 hover:text-primary"} px-3 py-2 rounded-md text-sm font-medium transition-colors`}>Home</Link>
<Link to="/products" className={`${darkMode ? "text-light hover:text-primary" : "text-gray-700 hover:text-primary"} px-3 py-2 rounded-md text-sm font-medium transition-colors`}>Products</Link>
<Link to="/about" className={`${darkMode ? "text-light hover:text-primary" : "text-gray-700 hover:text-primary"} px-3 py-2 rounded-md text-sm font-medium transition-colors`}>About us</Link>
{isAdmin && (
<div className="relative">
<button
onClick={() => setAdminMenuOpen(!adminMenuOpen)}
className={`${darkMode ? 'text-light hover:text-primary' : 'text-gray-700 hover:text-primary'} px-3 py-2 rounded-md text-sm font-medium flex items-center transition-colors`}
className={`${darkMode ? "text-light hover:text-primary" : "text-gray-700 hover:text-primary"} px-3 py-2 rounded-md text-sm font-medium flex items-center transition-colors`}
>
Admin
<svg
className={`ml-1 h-4 w-4 transform ${adminMenuOpen ? 'rotate-180' : ''} transition-transform`}
className={`ml-1 h-4 w-4 transform ${adminMenuOpen ? "rotate-180" : ""} transition-transform`}
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
Expand All @@ -50,11 +50,11 @@ export default function Navigation() {
</svg>
</button>
{adminMenuOpen && (
<div className={`absolute right-0 mt-2 w-48 rounded-md shadow-lg ${darkMode ? 'bg-dark' : 'bg-white'} ring-1 ring-black ring-opacity-5 transition-colors`}>
<div className={`absolute right-0 mt-2 w-48 rounded-md shadow-lg ${darkMode ? "bg-dark" : "bg-white"} ring-1 ring-black ring-opacity-5 transition-colors`}>
<div className="py-1">
<Link
to="/admin/products"
className={`block px-4 py-2 text-sm ${darkMode ? 'text-light hover:bg-primary hover:text-white' : 'text-gray-700 hover:bg-primary hover:text-white'} transition-colors`}
className={`block px-4 py-2 text-sm ${darkMode ? "text-light hover:bg-primary hover:text-white" : "text-gray-700 hover:bg-primary hover:text-white"} transition-colors`}
onClick={() => setAdminMenuOpen(false)}
>
Manage Products
Expand Down Expand Up @@ -85,13 +85,13 @@ export default function Navigation() {
</button>
{isLoggedIn ? (
<>
<span className={`${darkMode ? 'text-light' : 'text-gray-700'} text-sm transition-colors`}>
<span className={`${darkMode ? "text-light" : "text-gray-700"} text-sm transition-colors`}>
{isAdmin && <span className="text-primary">(Admin) </span>}
Welcome!
</span>
<button
onClick={logout}
className={`${darkMode ? 'text-light hover:text-primary' : 'text-gray-700 hover:text-primary'} px-3 py-2 rounded-md text-sm font-medium transition-colors`}
className={`${darkMode ? "text-light hover:text-primary" : "text-gray-700 hover:text-primary"} px-3 py-2 rounded-md text-sm font-medium transition-colors`}
>
Logout
</button>
Expand Down
Loading