diff --git a/.env.example b/.env.example
index b87d9f0..f21daf3 100644
--- a/.env.example
+++ b/.env.example
@@ -1,5 +1,5 @@
# API base URL for the backend that wraps the abra CLI
VITE_API_URL=http://localhost:3000/api
-# Set to 'true' to bypass authentication for development
+# Set to 'true' to use mock data
VITE_MOCK_AUTH=true
\ No newline at end of file
diff --git a/Netlify.toml b/Netlify.toml
deleted file mode 100644
index 8739f75..0000000
--- a/Netlify.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[build]
- command = "npm run build"
- publish = "dist"
-
-# Environment variables for build
-[build.environment]
- VITE_MOCK_AUTH = "true"
- VITE_API_URL = "http://localhost:3000/api"
-
-# Redirect all requests to index.html for client-side routing
-[[redirects]]
- from = "/*"
- to = "/index.html"
- status = 200
diff --git a/src/App.tsx b/src/App.tsx
index 483e2ea..d424307 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,35 +1,24 @@
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
-import { AuthProvider } from './context/AuthContext';
-import { LoginForm } from './routes/Login/LoginForm';
-import { Authenticated } from './components/Authenticated';
-import { Dashboard } from './routes/Authenticated/Dashboard/Dashboard';
-import { Apps } from './routes/Authenticated/Apps/Apps';
-import { AppDetail } from './routes/Authenticated/Apps/App';
-import { Servers } from './routes/Authenticated/Servers/Servers';
-import { Server } from './routes/Authenticated/Servers/Server';
+import { Dashboard } from './routes/Dashboard/Dashboard';
+import { Apps } from './routes/Apps/Apps';
+import { AppDetail } from './routes/Apps/App';
+import { Servers } from './routes/Servers/Servers';
+import { Server } from './routes/Servers/Server';
function App() {
return (
-
-
- {/* Public routes */}
- } />
-
- {/* Protected routes */}
- }>
- } />
- } />
- } />
- } />
- } />
- } />
-
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
{/* 404 catch-all */}
} />
-
);
}
diff --git a/src/components/Authenticated.tsx b/src/components/Authenticated.tsx
deleted file mode 100644
index 4d877a3..0000000
--- a/src/components/Authenticated.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react';
-import { Navigate, Outlet } from 'react-router-dom';
-import { useAuth } from '../context/AuthContext';
-
-export const Authenticated: React.FC = () => {
- const { isAuthenticated, loading } = useAuth();
-
- console.log('Authenticated:', { isAuthenticated, loading });
-
- if (loading) {
- return (
-
- );
- }
-
- return isAuthenticated ? : ;
-};
diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx
index 40f59cd..3a8fc9b 100644
--- a/src/components/Header/Header.tsx
+++ b/src/components/Header/Header.tsx
@@ -1,6 +1,5 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
-import { useAuth } from '../../context/AuthContext';
import './_Header.scss';
import logo from '../../assets/coopcloud_logo_grey.svg';
@@ -10,13 +9,7 @@ interface HeaderProps {
}
export const Header: React.FC = ({ children }) => {
- const { user, logout } = useAuth();
const navigate = useNavigate();
-
- const handleLogout = async () => {
- await logout();
- navigate('/login');
- };
return(
)}
\ No newline at end of file
diff --git a/src/components/Header/_Header.scss b/src/components/Header/_Header.scss
index 9b8f02b..3219edb 100644
--- a/src/components/Header/_Header.scss
+++ b/src/components/Header/_Header.scss
@@ -78,50 +78,4 @@
font-size: $font-size-xl;
}
}
-
- .user-menu {
- display: flex;
- align-items: center;
- gap: $spacing-lg;
-
- @media (max-width: 768px) {
- width: 100%;
- justify-content: space-between;
- }
-
- .username {
- font-weight: $font-weight-medium;
- font-size: $font-size-base;
-
- @media (max-width: 480px) {
- font-size: $font-size-sm;
- }
- }
-
- .logout-button {
- background: rgba(255, 255, 255, 0.2);
- border: 1px solid rgba(255, 255, 255, 0.4);
- color: $text-primary;
- padding: $spacing-sm $spacing-lg;
- border-radius: $radius-md;
- cursor: pointer;
- transition: all $transition-base;
- font-weight: $font-weight-medium;
-
- &:hover {
- background: rgba(255, 255, 255, 0.3);
- transform: translateY(-1px);
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
- }
-
- &:active {
- transform: translateY(0);
- }
-
- @media (max-width: 480px) {
- padding: $spacing-sm $spacing-md;
- font-size: $font-size-sm;
- }
- }
- }
}
\ No newline at end of file
diff --git a/src/context/AuthContext.tsx b/src/context/AuthContext.tsx
deleted file mode 100644
index de24c85..0000000
--- a/src/context/AuthContext.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
-import { apiService } from '../services/api';
-import type { User } from '../types';
-
-interface AuthContextType {
- user: User | null;
- isAuthenticated: boolean;
- loading: boolean;
- login: (credentials: { username: string; password: string }) => Promise;
- logout: () => void;
-}
-
-const AuthContext = createContext(undefined);
-
-export const useAuth = () => {
- const context = useContext(AuthContext);
- if (!context) {
- throw new Error('useAuth must be used within an AuthProvider');
- }
- return context;
-};
-
-interface AuthProviderProps {
- children: ReactNode;
-}
-
-export const AuthProvider: React.FC = ({ children }) => {
- const [user, setUser] = useState(null);
- const [isAuthenticated, setIsAuthenticated] = useState(false);
- const [loading, setLoading] = useState(true);
-
- // Check for existing session on mount
- useEffect(() => {
- const storedUser = localStorage.getItem('user');
-
- if (storedUser) {
- try {
- const parsedUser = JSON.parse(storedUser);
- setUser(parsedUser);
- setIsAuthenticated(true);
- } catch (err) {
- console.error('Failed to parse stored user:', err);
- localStorage.removeItem('user');
- }
- }
-
- setLoading(false);
- }, []);
-
-const login = async (credentials: { username: string; password: string }) => {
- const response = await apiService.login(credentials);
- setUser(response.user);
- setIsAuthenticated(true);
- localStorage.setItem('user', JSON.stringify(response.user));
-};
-
- const logout = () => {
- apiService.logout();
- setUser(null);
- setIsAuthenticated(false);
- localStorage.removeItem('user');
- };
-
- return (
-
- {children}
-
- );
-};
diff --git a/src/routes/Authenticated/Apps/App.scss b/src/routes/Apps/App.scss
similarity index 100%
rename from src/routes/Authenticated/Apps/App.scss
rename to src/routes/Apps/App.scss
diff --git a/src/routes/Authenticated/Apps/App.tsx b/src/routes/Apps/App.tsx
similarity index 96%
rename from src/routes/Authenticated/Apps/App.tsx
rename to src/routes/Apps/App.tsx
index 4467a7a..636e15a 100644
--- a/src/routes/Authenticated/Apps/App.tsx
+++ b/src/routes/Apps/App.tsx
@@ -1,10 +1,10 @@
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
-import { Header } from '../../../components/Header/Header';
-import { Terminal } from '../../../components/Terminal/Terminal';
-import { apiService } from '../../../services/api';
-import type { AbraApp } from '../../../types';
-import type { LogEntry } from '../../../services/mockApi';
+import { Header } from '../../components/Header/Header';
+import { Terminal } from '../../components/Terminal/Terminal';
+import { apiService } from '../../services/api';
+import type { AbraApp } from '../../types';
+import type { LogEntry } from '../../services/mockApi';
import './App.scss';
export const AppDetail: React.FC = () => {
@@ -26,7 +26,7 @@ export const AppDetail: React.FC = () => {
const fetchApp = async () => {
try {
if (isMockMode) {
- const { mockApiService } = await import('../../../services/mockApi');
+ const { mockApiService } = await import('../../services/mockApi');
const appsData = await mockApiService.getAppsGrouped();
const serverApps = appsData[server || ''];
@@ -67,7 +67,7 @@ export const AppDetail: React.FC = () => {
try {
if (isMockMode) {
- const { mockApiService } = await import('../../../services/mockApi');
+ const { mockApiService } = await import('../../services/mockApi');
const onLog = (log: LogEntry) => {
setTerminalLogs(prev => [...prev, log]);
diff --git a/src/routes/Authenticated/Apps/Apps.scss b/src/routes/Apps/Apps.scss
similarity index 100%
rename from src/routes/Authenticated/Apps/Apps.scss
rename to src/routes/Apps/Apps.scss
diff --git a/src/routes/Authenticated/Apps/Apps.tsx b/src/routes/Apps/Apps.tsx
similarity index 97%
rename from src/routes/Authenticated/Apps/Apps.tsx
rename to src/routes/Apps/Apps.tsx
index f0aadb0..1901f5a 100644
--- a/src/routes/Authenticated/Apps/Apps.tsx
+++ b/src/routes/Apps/Apps.tsx
@@ -1,8 +1,8 @@
import React, { useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
-import { Header } from '../../../components/Header/Header';
-import { apiService } from '../../../services/api';
-import type { AbraApp, AppWithServer, ServerAppsResponse } from '../../../types';
+import { Header } from '../../components/Header/Header';
+import { apiService } from '../../services/api';
+import type { AbraApp, AppWithServer, ServerAppsResponse } from '../../types';
import './Apps.scss';
export const Apps: React.FC = () => {
@@ -21,7 +21,7 @@ export const Apps: React.FC = () => {
const fetchData = async () => {
try {
if (isMockMode) {
- const { mockApiService } = await import('../../../services/mockApi');
+ const { mockApiService } = await import('../../services/mockApi');
const data = await mockApiService.getAppsGrouped();
setAppsData(data);
} else {
diff --git a/src/routes/Authenticated/Dashboard/Dashboard.tsx b/src/routes/Dashboard/Dashboard.tsx
similarity index 94%
rename from src/routes/Authenticated/Dashboard/Dashboard.tsx
rename to src/routes/Dashboard/Dashboard.tsx
index 3788542..c8bd091 100644
--- a/src/routes/Authenticated/Dashboard/Dashboard.tsx
+++ b/src/routes/Dashboard/Dashboard.tsx
@@ -1,8 +1,8 @@
import React, { useEffect, useState } from 'react';
-import { Header } from '../../../components/Header/Header';
+import { Header } from '../../components/Header/Header';
import { useNavigate } from 'react-router-dom';
-import { apiService } from '../../../services/api';
-import type { AbraApp, AbraServer } from '../../../types';
+import { apiService } from '../../services/api';
+import type { AbraApp, AbraServer } from '../../types';
import './_Dashboard.scss';
export const Dashboard: React.FC = () => {
@@ -19,7 +19,7 @@ export const Dashboard: React.FC = () => {
try {
if (isMockMode) {
// Use mock API in development
- const { mockApiService } = await import('../../../services/mockApi');
+ const { mockApiService } = await import('../../services/mockApi');
const [appsData, serversData] = await Promise.all([
mockApiService.getAppsGrouped(),
mockApiService.getServers(),
diff --git a/src/routes/Authenticated/Dashboard/_Dashboard.scss b/src/routes/Dashboard/_Dashboard.scss
similarity index 100%
rename from src/routes/Authenticated/Dashboard/_Dashboard.scss
rename to src/routes/Dashboard/_Dashboard.scss
diff --git a/src/routes/Login/LoginForm.scss b/src/routes/Login/LoginForm.scss
deleted file mode 100644
index 90e259b..0000000
--- a/src/routes/Login/LoginForm.scss
+++ /dev/null
@@ -1,94 +0,0 @@
-@use '../../assets/scss/variables' as *;
-@use '../../assets/scss/mixins' as *;
-
-.login-container {
- @include flex-center;
- min-height: 100vh;
- width: 100%;
- // @include gradient-primary;
- background-color: $primary-light;
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
-}
-
-.login-card {
- @include card;
- width: 100%;
- max-width: 400px;
-
- h1 {
- margin: 0 0 $spacing-sm;
- font-size: $font-size-3xl;
- color: $text-primary;
- text-align: center;
- }
-
- .login-subtitle {
- text-align: center;
- color: $text-secondary;
- margin: 0 0 $spacing-2xl;
- font-size: $font-size-sm;
- }
-}
-
-.form-group {
- margin-bottom: $spacing-lg;
-
- label {
- display: block;
- margin-bottom: $spacing-sm;
- color: $text-primary;
- font-weight: $font-weight-medium;
- font-size: $font-size-sm;
- }
-
- input {
- width: 100%;
- padding: $spacing-md;
- border: 2px solid $border-color;
- border-radius: $radius-md;
- font-size: $font-size-base;
- transition: border-color $transition-base;
- box-sizing: border-box;
-
- &:focus {
- outline: none;
- border-color: $primary;
- }
-
- &:disabled {
- background-color: $bg-secondary;
- cursor: not-allowed;
- }
- }
-}
-
-.error-message {
- // background-color: rgba($error, 0.1);
- // color: darken($error, 10%);
- padding: $spacing-md;
- border-radius: $radius-md;
- margin-bottom: $spacing-md;
- font-size: $font-size-sm;
- // border-left: 4px solid $error;
-}
-
-.login-button {
- @include button-base;
- @include gradient-primary;
- width: 100%;
- color: white;
- font-size: $font-size-base;
-
- &:hover:not(:disabled) {
- transform: translateY(-2px);
- box-shadow: 0 8px 16px rgba($primary, 0.4);
- }
-
- &:active:not(:disabled) {
- transform: translateY(0);
- }
-}
\ No newline at end of file
diff --git a/src/routes/Login/LoginForm.tsx b/src/routes/Login/LoginForm.tsx
deleted file mode 100644
index b9cdc3b..0000000
--- a/src/routes/Login/LoginForm.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-import React, { useState } from 'react';
-import { useNavigate } from 'react-router-dom';
-import { useAuth } from '../../context/AuthContext';
-import './LoginForm.scss';
-
-export const LoginForm: React.FC = () => {
- const [username, setUsername] = useState('');
- const [password, setPassword] = useState('');
- const [error, setError] = useState('');
- const [loading, setLoading] = useState(false);
-
- const { login } = useAuth();
- const navigate = useNavigate();
-
- const handleSubmit = async (e: React.FormEvent) => {
- e.preventDefault();
- setError('');
- setLoading(true);
-
- try {
- await login({ username, password });
- navigate('/dashboard');
- } catch (err) {
- setError(err instanceof Error ? err.message : 'Login failed');
- } finally {
- setLoading(false);
- }
- };
-
- return (
-
-
-
Coop Cloud
-
Sign in to manage your applications
-
-
-
-
- );
-};
\ No newline at end of file
diff --git a/src/routes/Authenticated/Servers/Server.scss b/src/routes/Servers/Server.scss
similarity index 100%
rename from src/routes/Authenticated/Servers/Server.scss
rename to src/routes/Servers/Server.scss
diff --git a/src/routes/Authenticated/Servers/Server.tsx b/src/routes/Servers/Server.tsx
similarity index 96%
rename from src/routes/Authenticated/Servers/Server.tsx
rename to src/routes/Servers/Server.tsx
index 5f38523..7c85bd4 100644
--- a/src/routes/Authenticated/Servers/Server.tsx
+++ b/src/routes/Servers/Server.tsx
@@ -1,10 +1,10 @@
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
-import { Header } from '../../../components/Header/Header';
-import { Terminal } from '../../../components/Terminal/Terminal';
-import { apiService } from '../../../services/api';
-import type { AbraServer, ServerAppsResponse } from '../../../types';
-import type { LogEntry } from '../../../services/mockApi';
+import { Header } from '../../components/Header/Header';
+import { Terminal } from '../../components/Terminal/Terminal';
+import { apiService } from '../../services/api';
+import type { AbraServer, ServerAppsResponse } from '../../types';
+import type { LogEntry } from '../../services/mockApi';
import './Server.scss';
interface ServerWithApps extends AbraServer {
@@ -35,7 +35,7 @@ export const Server: React.FC = () => {
const fetchServer = async () => {
try {
if (isMockMode) {
- const { mockApiService } = await import('../../../services/mockApi');
+ const { mockApiService } = await import('../../services/mockApi');
const appsData = await mockApiService.getAppsGrouped();
const serversData = await mockApiService.getServers();
@@ -95,7 +95,7 @@ export const Server: React.FC = () => {
try {
if (isMockMode) {
- const { mockApiService } = await import('../../../services/mockApi');
+ const { mockApiService } = await import('../../services/mockApi');
const onLog = (log: LogEntry) => {
setTerminalLogs(prev => [...prev, log]);
diff --git a/src/routes/Authenticated/Servers/Servers.scss b/src/routes/Servers/Servers.scss
similarity index 100%
rename from src/routes/Authenticated/Servers/Servers.scss
rename to src/routes/Servers/Servers.scss
diff --git a/src/routes/Authenticated/Servers/Servers.tsx b/src/routes/Servers/Servers.tsx
similarity index 97%
rename from src/routes/Authenticated/Servers/Servers.tsx
rename to src/routes/Servers/Servers.tsx
index 95c369a..714ad89 100644
--- a/src/routes/Authenticated/Servers/Servers.tsx
+++ b/src/routes/Servers/Servers.tsx
@@ -1,8 +1,8 @@
import React, { useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
-import { Header } from '../../../components/Header/Header';
-import { apiService } from '../../../services/api';
-import type { AbraServer, ServerAppsResponse } from '../../../types';
+import { Header } from '../../components/Header/Header';
+import { apiService } from '../../services/api';
+import type { AbraServer, ServerAppsResponse } from '../../types';
import './Servers.scss';
interface ServerWithStats extends AbraServer {
@@ -27,7 +27,7 @@ export const Servers: React.FC = () => {
const fetchData = async () => {
try {
if (isMockMode) {
- const { mockApiService } = await import('../../../services/mockApi');
+ const { mockApiService } = await import('../../services/mockApi');
const [serversData, appsData] = await Promise.all([
mockApiService.getServers(),
mockApiService.getAppsGrouped(),
diff --git a/src/types/index.ts b/src/types/index.ts
index a3ab2ac..b4e1d1d 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,19 +1,3 @@
-export interface User {
- id: string;
- username: string;
- email: string;
-}
-
-export interface AuthResponse {
- user: User;
- token: string;
-}
-
-export interface LoginCredentials {
- username: string;
- password: string;
-}
-
export interface ApiError {
message: string;
status: number;