` in `
` + - Update global CSS to new layout (see above) +4. **Verify** with `agent-browser screenshot` that the layout renders correctly + +## Quality checks (run before reporting done) + +- [ ] Sidebar renders at correct width, right-border visible +- [ ] All 7 nav items present with correct icons +- [ ] Active item highlighted on current route +- [ ] Collapse toggle works, persists on refresh (localStorage) +- [ ] Collapsed mode: icons only, no label overflow +- [ ] FilterBar still visible above content +- [ ] No horizontal scrollbar on content area +- [ ] Existing cards, tables, badges unchanged in content views + +## Collapsible iteration (after initial implementation) + +If the task includes "collapsible with icons-only mode": +- The toggle button should be at the bottom of the nav items area, not in a header +- Use a `` with `width`/`opacity` for label animation +- CSS transition: `transition: width 0.2s ease` on the sidebar itself +- `title` attribute on collapsed nav items for native tooltip (no JS needed) diff --git a/client/src/App.vue b/client/src/App.vue index c2da05a5c..9c2f67696 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -1,42 +1,15 @@ @@ -37,11 +49,15 @@ import { ref, onMounted, computed } from 'vue' import { api } from './api' import { useAuth } from './composables/useAuth' import { useBrainrot } from './composables/useBrainrot' +import { useWorksCouncil } from './composables/useWorksCouncil' import FilterBar from './components/FilterBar.vue' import ProfileDetailsModal from './components/ProfileDetailsModal.vue' import TasksModal from './components/TasksModal.vue' import AppSidebar from './components/AppSidebar.vue' import BrainrotPanel from './components/BrainrotPanel.vue' +import GdprCookieBanner from './components/GdprCookieBanner.vue' +import WorksCouncilModal from './components/WorksCouncilModal.vue' +import RightToDisconnectBanner from './components/RightToDisconnectBanner.vue' export default { name: 'App', @@ -50,11 +66,15 @@ export default { ProfileDetailsModal, TasksModal, AppSidebar, - BrainrotPanel + BrainrotPanel, + GdprCookieBanner, + WorksCouncilModal, + RightToDisconnectBanner }, setup() { const { currentUser } = useAuth() const { brainrotEnabled, toggle } = useBrainrot() + const { isOpen: wcIsOpen, actionDescription: wcActionDescription, handleOverride: wcHandleOverride, handleClose: wcHandleClose } = useWorksCouncil() const showProfileDetails = ref(false) const showTasks = ref(false) const apiTasks = ref([]) @@ -134,7 +154,11 @@ export default { deleteTask, toggleTask, brainrotEnabled, - toggle + toggle, + wcIsOpen, + wcActionDescription, + wcHandleOverride, + wcHandleClose } } } diff --git a/client/src/api.js b/client/src/api.js index 030b6aa10..9f39adea2 100644 --- a/client/src/api.js +++ b/client/src/api.js @@ -3,12 +3,12 @@ import axios from 'axios' const API_BASE_URL = 'http://localhost:8001/api' export const api = { - async getInventory(filters = {}) { + async getInventory(filters = {}, { signal } = {}) { const params = new URLSearchParams() if (filters.warehouse && filters.warehouse !== 'all') params.append('warehouse', filters.warehouse) if (filters.category && filters.category !== 'all') params.append('category', filters.category) - const response = await axios.get(`${API_BASE_URL}/inventory?${params.toString()}`) + const response = await axios.get(`${API_BASE_URL}/inventory?${params.toString()}`, { signal }) return response.data }, @@ -17,14 +17,14 @@ export const api = { return response.data }, - async getOrders(filters = {}) { + async getOrders(filters = {}, { signal } = {}) { const params = new URLSearchParams() if (filters.warehouse && filters.warehouse !== 'all') params.append('warehouse', filters.warehouse) if (filters.category && filters.category !== 'all') params.append('category', filters.category) if (filters.status && filters.status !== 'all') params.append('status', filters.status) if (filters.month && filters.month !== 'all') params.append('month', filters.month) - const response = await axios.get(`${API_BASE_URL}/orders?${params.toString()}`) + const response = await axios.get(`${API_BASE_URL}/orders?${params.toString()}`, { signal }) return response.data }, @@ -33,44 +33,44 @@ export const api = { return response.data }, - async getDemandForecasts() { - const response = await axios.get(`${API_BASE_URL}/demand`) + async getDemandForecasts({ signal } = {}) { + const response = await axios.get(`${API_BASE_URL}/demand`, { signal }) return response.data }, - async getBacklog() { - const response = await axios.get(`${API_BASE_URL}/backlog`) + async getBacklog({ signal } = {}) { + const response = await axios.get(`${API_BASE_URL}/backlog`, { signal }) return response.data }, - async getDashboardSummary(filters = {}) { + async getDashboardSummary(filters = {}, { signal } = {}) { const params = new URLSearchParams() if (filters.warehouse && filters.warehouse !== 'all') params.append('warehouse', filters.warehouse) if (filters.category && filters.category !== 'all') params.append('category', filters.category) if (filters.status && filters.status !== 'all') params.append('status', filters.status) if (filters.month && filters.month !== 'all') params.append('month', filters.month) - const response = await axios.get(`${API_BASE_URL}/dashboard/summary?${params.toString()}`) + const response = await axios.get(`${API_BASE_URL}/dashboard/summary?${params.toString()}`, { signal }) return response.data }, - async getSpendingSummary() { - const response = await axios.get(`${API_BASE_URL}/spending/summary`) + async getSpendingSummary({ signal } = {}) { + const response = await axios.get(`${API_BASE_URL}/spending/summary`, { signal }) return response.data }, - async getMonthlySpending() { - const response = await axios.get(`${API_BASE_URL}/spending/monthly`) + async getMonthlySpending({ signal } = {}) { + const response = await axios.get(`${API_BASE_URL}/spending/monthly`, { signal }) return response.data }, - async getCategorySpending() { - const response = await axios.get(`${API_BASE_URL}/spending/categories`) + async getCategorySpending({ signal } = {}) { + const response = await axios.get(`${API_BASE_URL}/spending/categories`, { signal }) return response.data }, - async getTransactions() { - const response = await axios.get(`${API_BASE_URL}/spending/transactions`) + async getTransactions({ signal } = {}) { + const response = await axios.get(`${API_BASE_URL}/spending/transactions`, { signal }) return response.data }, diff --git a/client/src/components/AppSidebar.vue b/client/src/components/AppSidebar.vue index 49f61aac0..ba15df347 100644 --- a/client/src/components/AppSidebar.vue +++ b/client/src/components/AppSidebar.vue @@ -72,6 +72,21 @@
+ + +