Frontend Overview
The frontend is a Vue 3 Single Page Application located at apps/frontend/. It uses Vite as the build tool and targets modern browsers.
Package Details
| Field | Value |
|---|---|
| Package | @my-app/frontend |
| Version | 5.5.0 |
| Framework | Vue 3 + Composition API |
| Build tool | Vite 6 |
| UI library | Element Plus 2.x |
| State | Pinia + persistedstate plugin |
| Routing | Vue Router 4 (hash history) |
| HTTP client | Axios (withCredentials) |
| Charts | ECharts 5 + vue-echarts |
| Reports | SheetJS (XLSX) |
Directory Structure
apps/frontend/src/
├── main.ts ← App bootstrap
├── App.vue ← Root component (el-config-provider)
├── vite-env.d.ts ← Vite env type declarations
│
├── router/
│ └── index.ts ← Routes + beforeEach auth guard
│
├── store/ ← Pinia state stores
│ ├── authStore.js ← User session (persisted)
│ ├── menuStore.ts ← Sidebar expand/collapse
│ ├── theme.ts ← Theme colors (CSS vars)
│ ├── tabs.ts ← Tab navigation state
│ └── sidebar.ts ← Sidebar color + collapse
│
├── views/ ← Page-level Vue components (lazy-loaded)
│ ├── signin.vue
│ ├── signup.vue
│ ├── signUpAndSignIn.vue
│ ├── home.vue ← Authenticated layout shell
│ ├── dashboard.vue
│ ├── live-alerts.vue
│ ├── current-conditions.vue
│ ├── reports.vue
│ ├── profile.vue
│ ├── settings.vue
│ ├── storage-settings.vue
│ ├── notification-settings.vue
│ ├── recipient-settings.vue
│ ├── device-settings.vue
│ └── admin/
│ ├── devices.vue
│ ├── users.vue
│ ├── sensorData.vue
│ ├── diagnosticData.vue
│ ├── rawSensorData.vue
│ └── deviceLogs.vue
│
├── components/ ← Reusable UI components
│ ├── header.vue
│ ├── sidebar.vue
│ ├── navBar.vue
│ ├── tabs.vue
│ ├── settingsMenu.vue
│ ├── signUpAndSignInHeader.vue
│ ├── countup.vue
│ └── pages/
│
├── utils/
│ ├── request.ts ← Axios instance
│ ├── notifications.ts ← ElNotification helpers
│ ├── env.ts ← Vite env helpers
│ └── index.ts ← CSS var utilities, color mixing
│
└── api/
└── index.ts ← Thin fetch wrappers (mock data helpers)Vite Configuration
File: apps/frontend/vite.config.ts
ts
// Key settings:
resolve.alias: { '@': '/src', '~': '/src/assets' }
define: { __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: "true" }
// Plugins:
vue()
VueSetupExtend()
AutoImport({ resolvers: [ElementPlusResolver()] })
Components({ resolvers: [ElementPlusResolver()] })Auto-Import Behaviour
unplugin-auto-import and unplugin-vue-components with ElementPlusResolver mean:
- All Element Plus components (
el-button,el-form,el-table, etc.) are available globally in templates — no import needed. - All Vue Composition API helpers (
ref,reactive,computed,watch,onMounted, etc.) are available in<script setup>— no import needed.
The generated type declarations live in auto-imports.d.ts and components.d.ts at the project root.
Bootstrap (src/main.ts)
ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { piniaPersist } from 'pinia-plugin-persistedstate'
import router from '@/router'
import * as Icons from '@element-plus/icons-vue'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()
pinia.use(piniaPersist)
// Register all Element Plus icons globally
for (const [name, Icon] of Object.entries(Icons)) {
app.component(name, Icon)
}
app.use(pinia).use(router).mount('#app')Key Dependencies
| Package | Purpose |
|---|---|
vue@^3.4.5 | Core framework |
element-plus@^2.6.3 | UI component library |
@element-plus/icons-vue | Icon components (registered globally) |
pinia@^2.1.7 | Global state management |
pinia-plugin-persistedstate | Persist Pinia stores to localStorage |
vue-router@^4.2.5 | Client-side routing |
axios@^1.6.3 | HTTP client |
echarts@^5.5.0 | Charts library |
vue-echarts@^6.6.9 | ECharts Vue wrapper |
xlsx@^0.18.5 | Excel/CSV import+export |
nprogress@^0.2.0 | Page-loading progress bar |
@wangeditor/editor-for-vue | Rich text editor component |
Component Pattern
All components use Vue 3 <script setup> syntax:
vue
<template>
<el-card>
<el-form :model="form" :rules="rules" ref="formRef">
<!-- Element Plus components are auto-imported -->
</el-form>
</el-card>
</template>
<script setup lang="ts">
// No need to import ref, reactive, etc. — auto-imported by Vite plugin
// No need to import el-card, el-form, etc. — auto-imported by Vite plugin
import { useAuthStore } from '@/store/authStore'
import type { User } from '@my-app/shared'
const form = reactive<Partial<User>>({ name: '', email: '' })
const formRef = ref<FormInstance>()
const auth = useAuthStore()
const handleSubmit = async () => {
await formRef.value?.validate(async (valid) => {
if (!valid) return
// call API
})
}
</script>