Skip to content
Open
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
1 change: 1 addition & 0 deletions client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Factory Inventory Management System</title>
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='6' fill='%230f172a'/%3E%3Crect x='8' y='14' width='16' height='10' rx='1.5' fill='%23e2e8f0'/%3E%3Crect x='11' y='9' width='10' height='6' rx='1' fill='%2364748b'/%3E%3C/svg%3E" />
</head>
<body>
<div id="app"></div>
Expand Down
151 changes: 92 additions & 59 deletions client/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,48 @@
<header class="top-nav">
<div class="nav-container">
<div class="logo">
<h1>{{ t('nav.companyName') }}</h1>
<span class="subtitle">{{ t('nav.subtitle') }}</span>
<h1>{{ t("nav.companyName") }}</h1>
<span class="subtitle">{{ t("nav.subtitle") }}</span>
</div>
<nav class="nav-tabs">
<router-link to="/" :class="{ active: $route.path === '/' }">
{{ t('nav.overview') }}
{{ t("nav.overview") }}
</router-link>
<router-link to="/inventory" :class="{ active: $route.path === '/inventory' }">
{{ t('nav.inventory') }}
<router-link
to="/inventory"
:class="{ active: $route.path === '/inventory' }"
>
{{ t("nav.inventory") }}
</router-link>
<router-link to="/orders" :class="{ active: $route.path === '/orders' }">
{{ t('nav.orders') }}
<router-link
to="/orders"
:class="{ active: $route.path === '/orders' }"
>
{{ t("nav.orders") }}
</router-link>
<router-link to="/spending" :class="{ active: $route.path === '/spending' }">
{{ t('nav.finance') }}
<router-link
to="/spending"
:class="{ active: $route.path === '/spending' }"
>
{{ t("nav.finance") }}
</router-link>
<router-link to="/demand" :class="{ active: $route.path === '/demand' }">
{{ t('nav.demandForecast') }}
<router-link
to="/demand"
:class="{ active: $route.path === '/demand' }"
>
{{ t("nav.demandForecast") }}
</router-link>
<router-link to="/reports" :class="{ active: $route.path === '/reports' }">
Reports
<router-link
to="/restocking"
:class="{ active: $route.path === '/restocking' }"
>
{{ t("nav.restocking") }}
</router-link>
<router-link
to="/reports"
:class="{ active: $route.path === '/reports' }"
>
{{ t("nav.reports") }}
</router-link>
</nav>
<LanguageSwitcher />
Expand Down Expand Up @@ -55,98 +76,101 @@
</template>

<script>
import { ref, onMounted, computed } from 'vue'
import { api } from './api'
import { useAuth } from './composables/useAuth'
import { useI18n } from './composables/useI18n'
import FilterBar from './components/FilterBar.vue'
import ProfileMenu from './components/ProfileMenu.vue'
import ProfileDetailsModal from './components/ProfileDetailsModal.vue'
import TasksModal from './components/TasksModal.vue'
import LanguageSwitcher from './components/LanguageSwitcher.vue'
import { ref, onMounted, computed } from "vue";
import { api } from "./api";
import { useAuth } from "./composables/useAuth";
import { useI18n } from "./composables/useI18n";
import FilterBar from "./components/FilterBar.vue";
import ProfileMenu from "./components/ProfileMenu.vue";
import ProfileDetailsModal from "./components/ProfileDetailsModal.vue";
import TasksModal from "./components/TasksModal.vue";
import LanguageSwitcher from "./components/LanguageSwitcher.vue";

export default {
name: 'App',
name: "App",
components: {
FilterBar,
ProfileMenu,
ProfileDetailsModal,
TasksModal,
LanguageSwitcher
LanguageSwitcher,
},
setup() {
const { currentUser } = useAuth()
const { t } = useI18n()
const showProfileDetails = ref(false)
const showTasks = ref(false)
const apiTasks = ref([])
const { currentUser } = useAuth();
const { t } = useI18n();
const showProfileDetails = ref(false);
const showTasks = ref(false);
const apiTasks = ref([]);

// Merge mock tasks from currentUser with API tasks
const tasks = computed(() => {
return [...currentUser.value.tasks, ...apiTasks.value]
})
return [...currentUser.value.tasks, ...apiTasks.value];
});

const loadTasks = async () => {
try {
apiTasks.value = await api.getTasks()
apiTasks.value = await api.getTasks();
} catch (err) {
console.error('Failed to load tasks:', err)
console.error("Failed to load tasks:", err);
}
}
};

const addTask = async (taskData) => {
try {
const newTask = await api.createTask(taskData)
const newTask = await api.createTask(taskData);
// Add new task to the beginning of the array
apiTasks.value.unshift(newTask)
apiTasks.value.unshift(newTask);
} catch (err) {
console.error('Failed to add task:', err)
console.error("Failed to add task:", err);
}
}
};

const deleteTask = async (taskId) => {
try {
// Check if it's a mock task (from currentUser)
const isMockTask = currentUser.value.tasks.some(t => t.id === taskId)
const isMockTask = currentUser.value.tasks.some((t) => t.id === taskId);

if (isMockTask) {
// Remove from mock tasks
const index = currentUser.value.tasks.findIndex(t => t.id === taskId)
const index = currentUser.value.tasks.findIndex(
(t) => t.id === taskId,
);
if (index !== -1) {
currentUser.value.tasks.splice(index, 1)
currentUser.value.tasks.splice(index, 1);
}
} else {
// Remove from API tasks
await api.deleteTask(taskId)
apiTasks.value = apiTasks.value.filter(t => t.id !== taskId)
await api.deleteTask(taskId);
apiTasks.value = apiTasks.value.filter((t) => t.id !== taskId);
}
} catch (err) {
console.error('Failed to delete task:', err)
console.error("Failed to delete task:", err);
}
}
};

const toggleTask = async (taskId) => {
try {
// Check if it's a mock task (from currentUser)
const mockTask = currentUser.value.tasks.find(t => t.id === taskId)
const mockTask = currentUser.value.tasks.find((t) => t.id === taskId);

if (mockTask) {
// Toggle mock task status
mockTask.status = mockTask.status === 'pending' ? 'completed' : 'pending'
mockTask.status =
mockTask.status === "pending" ? "completed" : "pending";
} else {
// Toggle API task
const updatedTask = await api.toggleTask(taskId)
const index = apiTasks.value.findIndex(t => t.id === taskId)
const updatedTask = await api.toggleTask(taskId);
const index = apiTasks.value.findIndex((t) => t.id === taskId);
if (index !== -1) {
apiTasks.value[index] = updatedTask
apiTasks.value[index] = updatedTask;
}
}
} catch (err) {
console.error('Failed to toggle task:', err)
console.error("Failed to toggle task:", err);
}
}
};

onMounted(loadTasks)
onMounted(loadTasks);

return {
t,
Expand All @@ -155,10 +179,10 @@ export default {
tasks,
addTask,
deleteTask,
toggleTask
}
}
}
toggleTask,
};
},
};
</script>

<style>
Expand All @@ -169,7 +193,16 @@ export default {
}

body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
font-family:
"Inter",
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
Oxygen,
Ubuntu,
Cantarell,
sans-serif;
background: #f8fafc;
color: #1e293b;
-webkit-font-smoothing: antialiased;
Expand Down Expand Up @@ -257,7 +290,7 @@ body {
}

.nav-tabs a.active::after {
content: '';
content: "";
position: absolute;
bottom: -1px;
left: 0;
Expand Down
Loading