+
diff --git a/frontend/components/Base/SectionHeader.vue b/frontend/components/Base/SectionHeader.vue
index 3e1e4e6..55cb21e 100644
--- a/frontend/components/Base/SectionHeader.vue
+++ b/frontend/components/Base/SectionHeader.vue
@@ -1,6 +1,12 @@
-
-
+
+
+
diff --git a/frontend/components/Form/Multiselect.vue b/frontend/components/Form/Multiselect.vue
index 57c8985..d03e7ac 100644
--- a/frontend/components/Form/Multiselect.vue
+++ b/frontend/components/Form/Multiselect.vue
@@ -9,7 +9,7 @@
-
+
+
+
+
+ {{ item.name }}
+
+
{{ item.description }}
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/components/Item/CreateModal.vue b/frontend/components/Item/CreateModal.vue
index 5a7dd1d..e1bbd23 100644
--- a/frontend/components/Item/CreateModal.vue
+++ b/frontend/components/Item/CreateModal.vue
@@ -26,6 +26,7 @@
-
-
-
- {{ label.name }}
-
+
+
+ {{ label.name }}
diff --git a/frontend/components/Location/Card.vue b/frontend/components/Location/Card.vue
new file mode 100644
index 0000000..e13be66
--- /dev/null
+++ b/frontend/components/Location/Card.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+ {{ location.name }}
+
+ {{ location.itemCount }}
+
+
+
+
+
+
diff --git a/frontend/lib/api/classes/items.ts b/frontend/lib/api/classes/items.ts
new file mode 100644
index 0000000..cba979e
--- /dev/null
+++ b/frontend/lib/api/classes/items.ts
@@ -0,0 +1,54 @@
+import { BaseAPI, UrlBuilder } from '../base';
+import { Label } from './labels';
+import { Location } from './locations';
+import { Results } from './types';
+
+export interface ItemCreate {
+ name: string;
+ description: string;
+ locationId: string;
+ labelIds: string[];
+}
+
+export interface Item {
+ createdAt: string;
+ description: string;
+ id: string;
+ labels: Label[];
+ location: Location;
+ manufacturer: string;
+ modelNumber: string;
+ name: string;
+ notes: string;
+ purchaseFrom: string;
+ purchasePrice: number;
+ purchaseTime: string;
+ serialNumber: string;
+ soldNotes: string;
+ soldPrice: number;
+ soldTime: string;
+ soldTo: string;
+ updatedAt: string;
+}
+
+export class ItemsApi extends BaseAPI {
+ async getAll() {
+ return this.http.get>(UrlBuilder('/items'));
+ }
+
+ async create(item: ItemCreate) {
+ return this.http.post(UrlBuilder('/items'), item);
+ }
+
+ async get(id: string) {
+ return this.http.get- (UrlBuilder(`/items/${id}`));
+ }
+
+ async delete(id: string) {
+ return this.http.delete(UrlBuilder(`/items/${id}`));
+ }
+
+ async update(id: string, item: ItemCreate) {
+ return this.http.put(UrlBuilder(`/items/${id}`), item);
+ }
+}
diff --git a/frontend/lib/api/classes/locations.ts b/frontend/lib/api/classes/locations.ts
index cff7904..f696744 100644
--- a/frontend/lib/api/classes/locations.ts
+++ b/frontend/lib/api/classes/locations.ts
@@ -1,4 +1,5 @@
import { BaseAPI, UrlBuilder } from '../base';
+import { Item } from './items';
import { Details, OutType, Results } from './types';
export type LocationCreate = Details;
@@ -6,6 +7,8 @@ export type LocationCreate = Details;
export type Location = LocationCreate &
OutType & {
groupId: string;
+ items: Item[];
+ itemCount: number;
};
export type LocationUpdate = LocationCreate;
diff --git a/frontend/lib/api/user.ts b/frontend/lib/api/user.ts
index ee39f1c..9df5ab5 100644
--- a/frontend/lib/api/user.ts
+++ b/frontend/lib/api/user.ts
@@ -1,5 +1,6 @@
import { Requests } from '~~/lib/requests';
import { BaseAPI, UrlBuilder } from './base';
+import { ItemsApi } from './classes/items';
import { LabelsApi } from './classes/labels';
import { LocationsApi } from './classes/locations';
@@ -17,11 +18,13 @@ export type User = {
export class UserApi extends BaseAPI {
locations: LocationsApi;
labels: LabelsApi;
+ items: ItemsApi;
constructor(requests: Requests) {
super(requests);
this.locations = new LocationsApi(requests);
this.labels = new LabelsApi(requests);
+ this.items = new ItemsApi(requests);
Object.freeze(this);
}
diff --git a/frontend/nuxt.config.ts b/frontend/nuxt.config.ts
index 898fc65..cabf97e 100644
--- a/frontend/nuxt.config.ts
+++ b/frontend/nuxt.config.ts
@@ -4,6 +4,10 @@ import { defineNuxtConfig } from 'nuxt';
export default defineNuxtConfig({
ssr: false,
modules: ['@nuxtjs/tailwindcss', '@pinia/nuxt', '@vueuse/nuxt'],
+ meta: {
+ title: 'Homebox',
+ link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.svg' }],
+ },
vite: {
server: {
proxy: {
diff --git a/frontend/pages/home.vue b/frontend/pages/home.vue
index 23f7dfe..540c8d3 100644
--- a/frontend/pages/home.vue
+++ b/frontend/pages/home.vue
@@ -17,33 +17,85 @@
const { data } = await api.labels.getAll();
return data.items;
});
+
+ const { data: items } = useAsyncData('items', async () => {
+ const { data } = await api.items.getAll();
+ return data.items;
+ });
+
+ const totalItems = computed(() => items.value?.length || 0);
+ const totalLocations = computed(() => locations.value?.length || 0);
+ const totalLabels = computed(() => labels.value?.length || 0);
+
+ const stats = [
+ {
+ label: 'Locations',
+ value: totalLocations,
+ },
+ {
+ label: 'Items',
+ value: totalItems,
+ },
+ {
+ label: 'Labels',
+ value: totalLabels,
+ },
+ ];
+
+
+
Profile Overview
+
+
+
+
+
Welcome back,
+
Hayden Kotelman
+
User
+
+
+
+
+
+
+
+ {{ stat.value.value }}
+ {{ ' ' }}
+ {{ stat.label }}
+
+
+
+
+
Storage Locations
-
-
-
-
-
- {{ l.name }}
-
-
-
-
+
+
+
+
+
+
diff --git a/frontend/pages/index.vue b/frontend/pages/index.vue
index cdc51bb..e650a31 100644
--- a/frontend/pages/index.vue
+++ b/frontend/pages/index.vue
@@ -11,6 +11,11 @@
layout: 'empty',
});
+ const authStore = useAuthStore();
+ if (!authStore.isTokenExpired) {
+ navigateTo('/home');
+ }
+
const registerFields = [
{
label: "What's your name?",
@@ -72,8 +77,6 @@
},
];
- const authStore = useAuthStore();
-
const toast = useNotifier();
const loading = ref(false);
diff --git a/frontend/pages/label/[id].vue b/frontend/pages/label/[id].vue
index a14588c..3814357 100644
--- a/frontend/pages/label/[id].vue
+++ b/frontend/pages/label/[id].vue
@@ -112,7 +112,7 @@
-
+
{{ label ? label.name : '' }}
diff --git a/frontend/pages/location/[id].vue b/frontend/pages/location/[id].vue
index 6d2e27d..67433c8 100644
--- a/frontend/pages/location/[id].vue
+++ b/frontend/pages/location/[id].vue
@@ -112,7 +112,7 @@
-
+
{{ location ? location.name : '' }}
@@ -127,8 +127,11 @@
-
+
diff --git a/frontend/public/favicon.svg b/frontend/public/favicon.svg
new file mode 100644
index 0000000..83cb12b
--- /dev/null
+++ b/frontend/public/favicon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/stores/auth.ts b/frontend/stores/auth.ts
index f2f1b43..5d9f30e 100644
--- a/frontend/stores/auth.ts
+++ b/frontend/stores/auth.ts
@@ -1,19 +1,19 @@
-import { UserApi } from "~~/lib/api/user";
-import { defineStore } from "pinia";
-import { useLocalStorage } from "@vueuse/core";
+import { UserApi } from '~~/lib/api/user';
+import { defineStore } from 'pinia';
+import { useLocalStorage } from '@vueuse/core';
-export const useAuthStore = defineStore("auth", {
+export const useAuthStore = defineStore('auth', {
state: () => ({
- token: useLocalStorage("pinia/auth/token", ""),
- expires: useLocalStorage("pinia/auth/expires", ""),
+ token: useLocalStorage('pinia/auth/token', ''),
+ expires: useLocalStorage('pinia/auth/expires', ''),
}),
getters: {
- isTokenExpired: (state) => {
+ isTokenExpired: state => {
if (!state.expires) {
return true;
}
- if (typeof state.expires === "string") {
+ if (typeof state.expires === 'string') {
return new Date(state.expires) < new Date();
}
@@ -28,8 +28,8 @@ export const useAuthStore = defineStore("auth", {
return result;
}
- this.token = "";
- this.expires = "";
+ this.token = '';
+ this.expires = '';
return result;
},