mirror of
https://github.com/hay-kot/homebox.git
synced 2025-08-03 08:10:28 +00:00
setup and run eslint
This commit is contained in:
parent
cf01003de2
commit
24f01fb58f
43 changed files with 1655 additions and 237 deletions
|
@ -8,5 +8,5 @@ insert_final_newline = true
|
|||
[*.{js,jsx,html,sass,vue,ts,tsx,json}]
|
||||
charset = utf-8
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
|
42
frontend/.eslintrc.json
Normal file
42
frontend/.eslintrc.json
Normal file
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:vue/essential",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"@nuxtjs/eslint-config-typescript",
|
||||
"plugin:vue/vue3-recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["vue", "@typescript-eslint"],
|
||||
"rules": {
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/no-setup-props-destructure": 0,
|
||||
"vue/no-multiple-template-root": 0,
|
||||
"no-console": 1,
|
||||
"vue/no-v-model-argument": 0,
|
||||
"@typescript-eslint/ban-ts-comment": 0,
|
||||
"prettier/prettier": [
|
||||
"warn",
|
||||
{
|
||||
"arrowParens": "avoid",
|
||||
"semi": true,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"vueIndentScriptAndStyle": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 120
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -66,7 +66,7 @@
|
|||
|
||||
<div class="bg-neutral absolute shadow-xl top-0 h-[50vh] max-h-96 sm:h-[28vh] -z-10 w-full"></div>
|
||||
|
||||
<BaseContainer is="header" class="py-6 max-w-none">
|
||||
<BaseContainer cmp="header" class="py-6 max-w-none">
|
||||
<BaseContainer>
|
||||
<h2 class="mt-1 text-4xl font-bold tracking-tight text-neutral-content sm:text-5xl lg:text-6xl flex">
|
||||
HomeB
|
||||
|
@ -77,20 +77,22 @@
|
|||
<template v-for="link in links">
|
||||
<NuxtLink
|
||||
v-if="!link.action"
|
||||
:key="link.name"
|
||||
class="hover:text-base-content transition-color duration-200 italic"
|
||||
:to="link.href"
|
||||
>
|
||||
{{ link.name }}
|
||||
</NuxtLink>
|
||||
<button
|
||||
for="location-form-modal"
|
||||
v-else
|
||||
@click="link.action"
|
||||
:key="link.name + 'link'"
|
||||
for="location-form-modal"
|
||||
class="hover:text-base-content transition-color duration-200 italic"
|
||||
@click="link.action"
|
||||
>
|
||||
{{ link.name }}
|
||||
</button>
|
||||
<span v-if="!link.last"> / </span>
|
||||
<span v-if="!link.last" :key="link.name"> / </span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="flex mt-6">
|
||||
|
@ -102,7 +104,7 @@
|
|||
Create
|
||||
</label>
|
||||
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52">
|
||||
<li v-for="btn in dropdown">
|
||||
<li v-for="btn in dropdown" :key="btn.name">
|
||||
<button @click="btn.action">
|
||||
{{ btn.name }}
|
||||
</button>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div class="divider">
|
||||
<div class="btn-group min-w-[180px] flex-nowrap">
|
||||
<button @click="$emit('edit')" name="options" class="btn btn-sm btn-primary">
|
||||
<button name="options" class="btn btn-sm btn-primary" @click="$emit('edit')">
|
||||
<Icon name="heroicons-pencil" class="h-5 w-5 mr-1" aria-hidden="true" />
|
||||
<span> Edit </span>
|
||||
</button>
|
||||
<button @click="$emit('delete')" name="options" class="btn btn-sm btn-primary">
|
||||
<button name="options" class="btn btn-sm btn-primary" @click="$emit('delete')">
|
||||
<Icon name="heroicons-trash" class="h-5 w-5 mr-1" aria-hidden="true" />
|
||||
<span> Delete </span>
|
||||
</button>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<NuxtLink
|
||||
v-if="to"
|
||||
:to="to"
|
||||
v-bind="attributes"
|
||||
class="btn"
|
||||
ref="submitBtn"
|
||||
:to="to"
|
||||
class="btn"
|
||||
:class="{
|
||||
loading: loading,
|
||||
'btn-sm': size === 'sm',
|
||||
|
@ -19,8 +19,8 @@
|
|||
<button
|
||||
v-else
|
||||
v-bind="attributes"
|
||||
class="btn"
|
||||
ref="submitBtn"
|
||||
class="btn"
|
||||
:class="{
|
||||
loading: loading,
|
||||
'btn-sm': size === 'sm',
|
||||
|
@ -67,13 +67,6 @@
|
|||
};
|
||||
});
|
||||
|
||||
const is = computed(() => {
|
||||
if (props.to) {
|
||||
return 'a';
|
||||
}
|
||||
return 'button';
|
||||
});
|
||||
|
||||
const submitBtn = ref(null);
|
||||
const isHover = useElementHover(submitBtn);
|
||||
</script>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
defineProps({
|
||||
is: {
|
||||
cmp: {
|
||||
type: String,
|
||||
default: 'div',
|
||||
},
|
||||
|
@ -8,7 +8,7 @@
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="is" class="container max-w-6xl mx-auto px-4">
|
||||
<component :is="cmp" class="container max-w-6xl mx-auto px-4">
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
</div>
|
||||
<div class="border-t border-gray-300 px-4 py-5 sm:p-0">
|
||||
<dl class="sm:divide-y sm:divide-gray-300">
|
||||
<div v-for="(dValue, dKey) in details" class="py-4 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<div v-for="(dValue, dKey) in details" :key="dKey" class="py-4 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium text-gray-500">
|
||||
{{ dKey }}
|
||||
</dt>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div class="z-[999]">
|
||||
<input type="checkbox" :id="modalId" class="modal-toggle" v-model="modal" />
|
||||
<input :id="modalId" v-model="modal" type="checkbox" class="modal-toggle" />
|
||||
<div class="modal modal-bottom sm:modal-middle overflow-visible">
|
||||
<div class="modal-box overflow-visible relative">
|
||||
<button @click="close" :for="modalId" class="btn btn-sm btn-circle absolute right-2 top-2">✕</button>
|
||||
<button :for="modalId" class="btn btn-sm btn-circle absolute right-2 top-2" @click="close">✕</button>
|
||||
|
||||
<h3 class="font-bold text-lg">
|
||||
<slot name="title"></slot>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="dropdown dropdown-end w-full" ref="label">
|
||||
<FormTextField tabindex="0" label="Date" v-model="dateText" :inline="inline" readonly />
|
||||
<div @blur="resetTime" tabindex="0" class="mt-1 card compact dropdown-content shadow bg-base-100 rounded-box w-64">
|
||||
<div ref="label" class="dropdown dropdown-end w-full">
|
||||
<FormTextField v-model="dateText" tabindex="0" label="Date" :inline="inline" readonly />
|
||||
<div tabindex="0" class="mt-1 card compact dropdown-content shadow bg-base-100 rounded-box w-64" @blur="resetTime">
|
||||
<div class="card-body">
|
||||
<div class="flex justify-between items-center">
|
||||
<button class="btn btn-xs" @click="prevMonth">
|
||||
|
@ -13,7 +13,7 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="grid grid-cols-7 gap-2">
|
||||
<div v-for="d in daysIdx">
|
||||
<div v-for="d in daysIdx" :key="d">
|
||||
<p class="text-center">
|
||||
{{ d }}
|
||||
</p>
|
||||
|
@ -21,12 +21,13 @@
|
|||
<template v-for="day in days">
|
||||
<button
|
||||
v-if="day.number != ''"
|
||||
:key="day.number"
|
||||
class="text-center btn-xs btn btn-outline"
|
||||
@click="select($event, day.date)"
|
||||
>
|
||||
{{ day.number }}
|
||||
</button>
|
||||
<div v-else></div>
|
||||
<div v-else :key="`${day.number}-empty`"></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -93,7 +94,7 @@
|
|||
console.log(day);
|
||||
selected.value = day;
|
||||
console.log(selected.value);
|
||||
// @ts-ignore
|
||||
// @ts-ignore - this is a vue3 bug
|
||||
e.target.blur();
|
||||
resetTime();
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<template>
|
||||
<div class="form-control w-full" ref="menu">
|
||||
<div ref="menu" class="form-control w-full">
|
||||
<label class="label">
|
||||
<span class="label-text">{{ label }}</span>
|
||||
</label>
|
||||
<div class="dropdown dropdown-top sm:dropdown-end">
|
||||
<div tabindex="0" class="w-full min-h-[48px] flex gap-2 p-4 flex-wrap border border-gray-400 rounded-lg">
|
||||
<span class="badge" v-for="itm in value"> {{ name != '' ? itm[name] : itm }} </span>
|
||||
<span v-for="itm in value" :key="name != '' ? itm[name] : itm" class="badge">
|
||||
{{ name != '' ? itm[name] : itm }}
|
||||
</span>
|
||||
</div>
|
||||
<ul
|
||||
tabindex="0"
|
||||
|
@ -13,6 +15,7 @@
|
|||
>
|
||||
<li
|
||||
v-for="(obj, idx) in items"
|
||||
:key="idx"
|
||||
:class="{
|
||||
bordered: selectedIndexes[idx],
|
||||
}"
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
<label class="label">
|
||||
<span class="label-text">{{ label }}</span>
|
||||
</label>
|
||||
<select class="select select-bordered" v-model="value">
|
||||
<select v-model="value" class="select select-bordered">
|
||||
<option disabled selected>Pick one</option>
|
||||
<option v-for="obj in items" :value="obj">
|
||||
<option v-for="obj in items" :key="name != '' ? obj[name] : obj" :value="obj">
|
||||
{{ name != '' ? obj[name] : obj }}
|
||||
</option>
|
||||
</select>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div class="form-control" v-if="!inline">
|
||||
<div v-if="!inline" class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">{{ label }}</span>
|
||||
</label>
|
||||
<textarea class="textarea textarea-bordered h-24" v-model="value" :placeholder="placeholder" />
|
||||
<textarea v-model="value" class="textarea textarea-bordered h-24" :placeholder="placeholder" />
|
||||
<label v-if="limit" class="label">
|
||||
<span class="label-text-alt"></span>
|
||||
<span class="label-text-alt"> {{ valueLen }}/{{ limit }}</span>
|
||||
|
@ -13,7 +13,12 @@
|
|||
<label class="label">
|
||||
<span class="label-text">{{ label }}</span>
|
||||
</label>
|
||||
<textarea class="textarea textarea-bordered col-span-3 mt-3 h-24" auto-grow v-model="value" :placeholder="placeholder" />
|
||||
<textarea
|
||||
v-model="value"
|
||||
class="textarea textarea-bordered col-span-3 mt-3 h-24"
|
||||
auto-grow
|
||||
:placeholder="placeholder"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
<label class="label">
|
||||
<span class="label-text">{{ label }}</span>
|
||||
</label>
|
||||
<input ref="input" :type="type" v-model="value" class="input input-bordered w-full" />
|
||||
<input ref="input" v-model="value" :type="type" class="input input-bordered w-full" />
|
||||
</div>
|
||||
<div v-else class="sm:grid sm:grid-cols-4 sm:items-start sm:gap-4">
|
||||
<label class="label">
|
||||
<span class="label-text">{{ label }}</span>
|
||||
</label>
|
||||
<input class="input input-bordered col-span-3 w-full mt-2" v-model="value" />
|
||||
<input v-model="value" class="input input-bordered col-span-3 w-full mt-2" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -10,7 +10,12 @@
|
|||
</h2>
|
||||
<p>{{ description }}</p>
|
||||
<div class="flex gap-2 flex-wrap justify-end">
|
||||
<LabelChip v-for="label in item.labels" :label="label" class="badge-primary group-hover:badge-secondary" />
|
||||
<LabelChip
|
||||
v-for="label in item.labels"
|
||||
:key="label.id"
|
||||
:label="label"
|
||||
class="badge-primary group-hover:badge-secondary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
<BaseModal v-model="modal">
|
||||
<template #title> Create Item </template>
|
||||
<form @submit.prevent="create">
|
||||
<FormSelect label="Location" v-model="form.location" :items="locations ?? []" select-first />
|
||||
<FormSelect v-model="form.location" label="Location" :items="locations ?? []" select-first />
|
||||
<FormTextField
|
||||
:trigger-focus="focused"
|
||||
ref="locationNameRef"
|
||||
v-model="form.name"
|
||||
:trigger-focus="focused"
|
||||
:autofocus="true"
|
||||
label="Item Name"
|
||||
v-model="form.name"
|
||||
/>
|
||||
<FormTextField label="Item Description" v-model="form.description" />
|
||||
<FormMultiselect label="Labels" v-model="form.labels" :items="labels ?? []" />
|
||||
<FormTextField v-model="form.description" label="Item Description" />
|
||||
<FormMultiselect v-model="form.labels" label="Labels" :items="labels ?? []" />
|
||||
<div class="modal-action">
|
||||
<BaseButton ref="submitBtn" type="submit" :loading="loading">
|
||||
<template #icon>
|
||||
|
@ -87,7 +87,7 @@
|
|||
labelIds: form.labels.map(l => l.id) as string[],
|
||||
};
|
||||
|
||||
const { data, error } = await api.items.create(out);
|
||||
const { error } = await api.items.create(out);
|
||||
if (error) {
|
||||
toast.error("Couldn't create label");
|
||||
return;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
export type sizes = 'sm' | 'md' | 'lg';
|
||||
|
||||
import { Label } from '~~/lib/api/classes/labels';
|
||||
|
||||
export type sizes = 'sm' | 'md' | 'lg';
|
||||
defineProps({
|
||||
label: {
|
||||
type: Object as () => Label,
|
||||
|
@ -22,12 +22,12 @@
|
|||
|
||||
<template>
|
||||
<NuxtLink
|
||||
ref="badge"
|
||||
class="badge"
|
||||
:class="{
|
||||
'p-3': size !== 'sm',
|
||||
'p-2 badge-sm': size === 'sm',
|
||||
}"
|
||||
ref="badge"
|
||||
:to="`/label/${label.id}`"
|
||||
>
|
||||
<label class="swap swap-rotate" :class="isActive ? 'swap-active' : ''">
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
<template #title> Create Label </template>
|
||||
<form @submit.prevent="create">
|
||||
<FormTextField
|
||||
:trigger-focus="focused"
|
||||
ref="locationNameRef"
|
||||
v-model="form.name"
|
||||
:trigger-focus="focused"
|
||||
:autofocus="true"
|
||||
label="Label Name"
|
||||
v-model="form.name"
|
||||
/>
|
||||
<FormTextField label="Label Description" v-model="form.description" />
|
||||
<FormTextField v-model="form.description" label="Label Description" />
|
||||
<div class="modal-action">
|
||||
<BaseButton type="submit" :loading="loading"> Create </BaseButton>
|
||||
</div>
|
||||
|
@ -54,7 +54,7 @@
|
|||
const toast = useNotifier();
|
||||
|
||||
async function create() {
|
||||
const { data, error } = await api.labels.create(form);
|
||||
const { error } = await api.labels.create(form);
|
||||
if (error) {
|
||||
toast.error("Couldn't create label");
|
||||
return;
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
<template #title> Create Location </template>
|
||||
<form @submit.prevent="create">
|
||||
<FormTextField
|
||||
:trigger-focus="focused"
|
||||
ref="locationNameRef"
|
||||
v-model="form.name"
|
||||
:trigger-focus="focused"
|
||||
:autofocus="true"
|
||||
label="Location Name"
|
||||
v-model="form.name"
|
||||
/>
|
||||
<FormTextField label="Location Description" v-model="form.description" />
|
||||
<FormTextField v-model="form.description" label="Location Description" />
|
||||
<div class="modal-action">
|
||||
<BaseButton type="submit" :loading="loading"> Create </BaseButton>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<BaseModal @cancel="cancel(false)" v-model="isRevealed" readonly>
|
||||
<BaseModal v-model="isRevealed" readonly @cancel="cancel(false)">
|
||||
<template #title> Confirm </template>
|
||||
<div>
|
||||
<p>{{ text }}</p>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { UseConfirmDialogReturn } from '@vueuse/core';
|
||||
import { Ref } from 'vue';
|
||||
|
||||
type Store = UseConfirmDialogReturn<any, Boolean, Boolean> & {
|
||||
type Store = UseConfirmDialogReturn<any, boolean, boolean> & {
|
||||
text: Ref<string>;
|
||||
setup: boolean;
|
||||
};
|
||||
|
@ -21,7 +21,7 @@ const store: Partial<Store> = {
|
|||
export function useConfirm(): Store {
|
||||
if (!store.setup) {
|
||||
store.setup = true;
|
||||
const { isRevealed, reveal, confirm, cancel } = useConfirmDialog<any, Boolean, Boolean>();
|
||||
const { isRevealed, reveal, confirm, cancel } = useConfirmDialog<any, boolean, boolean>();
|
||||
store.isRevealed = isRevealed;
|
||||
store.reveal = reveal;
|
||||
store.confirm = confirm;
|
||||
|
|
|
@ -1,31 +1,29 @@
|
|||
function slugify(text: string) {
|
||||
return text
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-') // Replace spaces with -
|
||||
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
|
||||
.replace(/\-\-+/g, '-') // Replace multiple - with single -
|
||||
.replace(/^-+/, '') // Trim - from start of text
|
||||
.replace(/-+$/, ''); // Trim - from end of text
|
||||
}
|
||||
|
||||
function idGenerator(): string {
|
||||
const id =
|
||||
Math.random().toString(32).substring(2, 6) +
|
||||
Math.random().toString(36).substring(2, 6);
|
||||
return slugify(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* useFormIds uses the provided label to generate a unique id for the
|
||||
* form element. If no label is provided the id is generated using a
|
||||
* random string.
|
||||
*/
|
||||
export function useFormIds(label: string): string {
|
||||
const slug = label ? slugify(label) : idGenerator();
|
||||
return `${slug}-${idGenerator()}`;
|
||||
}
|
||||
|
||||
export function useId(): string {
|
||||
return idGenerator();
|
||||
}
|
||||
function slugify(text: string) {
|
||||
return text
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-') // Replace spaces with -
|
||||
.replace(/[^\w-]+/g, '') // Remove all non-word chars
|
||||
.replace(/--+/g, '-') // Replace multiple - with single -
|
||||
.replace(/^-+/, '') // Trim - from start of text
|
||||
.replace(/-+$/, ''); // Trim - from end of text
|
||||
}
|
||||
|
||||
function idGenerator(): string {
|
||||
const id = Math.random().toString(32).substring(2, 6) + Math.random().toString(36).substring(2, 6);
|
||||
return slugify(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* useFormIds uses the provided label to generate a unique id for the
|
||||
* form element. If no label is provided the id is generated using a
|
||||
* random string.
|
||||
*/
|
||||
export function useFormIds(label: string): string {
|
||||
const slug = label ? slugify(label) : idGenerator();
|
||||
return `${slug}-${idGenerator()}`;
|
||||
}
|
||||
|
||||
export function useId(): string {
|
||||
return idGenerator();
|
||||
}
|
||||
|
|
|
@ -1,57 +1,55 @@
|
|||
import { useId } from './use-ids';
|
||||
|
||||
interface Notification {
|
||||
id: string;
|
||||
message: string;
|
||||
type: 'success' | 'error' | 'info';
|
||||
id: string;
|
||||
message: string;
|
||||
type: 'success' | 'error' | 'info';
|
||||
}
|
||||
|
||||
const notifications = ref<Notification[]>([]);
|
||||
|
||||
function addNotification(notification: Notification) {
|
||||
notifications.value.unshift(notification);
|
||||
notifications.value.unshift(notification);
|
||||
|
||||
if (notifications.value.length > 4) {
|
||||
notifications.value.pop();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
// Remove notification with ID
|
||||
notifications.value = notifications.value.filter(
|
||||
n => n.id !== notification.id
|
||||
);
|
||||
}, 5000);
|
||||
}
|
||||
if (notifications.value.length > 4) {
|
||||
notifications.value.pop();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
// Remove notification with ID
|
||||
notifications.value = notifications.value.filter(n => n.id !== notification.id);
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
export function useNotifications() {
|
||||
return {
|
||||
notifications,
|
||||
dropNotification: (idx: number) => notifications.value.splice(idx, 1),
|
||||
};
|
||||
return {
|
||||
notifications,
|
||||
dropNotification: (idx: number) => notifications.value.splice(idx, 1),
|
||||
};
|
||||
}
|
||||
|
||||
export function useNotifier() {
|
||||
return {
|
||||
success: (message: string) => {
|
||||
addNotification({
|
||||
id: useId(),
|
||||
message,
|
||||
type: 'success',
|
||||
});
|
||||
},
|
||||
error: (message: string) => {
|
||||
addNotification({
|
||||
id: useId(),
|
||||
message,
|
||||
type: 'error',
|
||||
});
|
||||
},
|
||||
info: (message: string) => {
|
||||
addNotification({
|
||||
id: useId(),
|
||||
message,
|
||||
type: 'info',
|
||||
});
|
||||
},
|
||||
};
|
||||
return {
|
||||
success: (message: string) => {
|
||||
addNotification({
|
||||
id: useId(),
|
||||
message,
|
||||
type: 'success',
|
||||
});
|
||||
},
|
||||
error: (message: string) => {
|
||||
addNotification({
|
||||
id: useId(),
|
||||
message,
|
||||
type: 'error',
|
||||
});
|
||||
},
|
||||
info: (message: string) => {
|
||||
addNotification({
|
||||
id: useId(),
|
||||
message,
|
||||
type: 'info',
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -35,11 +35,11 @@ export interface Item {
|
|||
}
|
||||
|
||||
export class ItemsApi extends BaseAPI {
|
||||
async getAll() {
|
||||
getAll() {
|
||||
return this.http.get<Results<Item>>({ url: route('/items') });
|
||||
}
|
||||
|
||||
async create(item: ItemCreate) {
|
||||
create(item: ItemCreate) {
|
||||
return this.http.post<ItemCreate, Item>({ url: route('/items'), body: item });
|
||||
}
|
||||
|
||||
|
@ -58,15 +58,15 @@ export class ItemsApi extends BaseAPI {
|
|||
return payload;
|
||||
}
|
||||
|
||||
async delete(id: string) {
|
||||
delete(id: string) {
|
||||
return this.http.delete<void>({ url: route(`/items/${id}`) });
|
||||
}
|
||||
|
||||
async update(id: string, item: ItemCreate) {
|
||||
update(id: string, item: ItemCreate) {
|
||||
return this.http.put<ItemCreate, Item>({ url: route(`/items/${id}`), body: item });
|
||||
}
|
||||
|
||||
async import(file: File) {
|
||||
import(file: File) {
|
||||
const formData = new FormData();
|
||||
formData.append('csv', file);
|
||||
|
||||
|
|
|
@ -15,23 +15,23 @@ export type Label = LabelCreate &
|
|||
};
|
||||
|
||||
export class LabelsApi extends BaseAPI {
|
||||
async getAll() {
|
||||
getAll() {
|
||||
return this.http.get<Results<Label>>({ url: route('/labels') });
|
||||
}
|
||||
|
||||
async create(body: LabelCreate) {
|
||||
create(body: LabelCreate) {
|
||||
return this.http.post<LabelCreate, Label>({ url: route('/labels'), body });
|
||||
}
|
||||
|
||||
async get(id: string) {
|
||||
get(id: string) {
|
||||
return this.http.get<Label>({ url: route(`/labels/${id}`) });
|
||||
}
|
||||
|
||||
async delete(id: string) {
|
||||
delete(id: string) {
|
||||
return this.http.delete<void>({ url: route(`/labels/${id}`) });
|
||||
}
|
||||
|
||||
async update(id: string, body: LabelUpdate) {
|
||||
update(id: string, body: LabelUpdate) {
|
||||
return this.http.put<LabelUpdate, Label>({ url: route(`/labels/${id}`), body });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,22 +14,23 @@ export type Location = LocationCreate &
|
|||
export type LocationUpdate = LocationCreate;
|
||||
|
||||
export class LocationsApi extends BaseAPI {
|
||||
async getAll() {
|
||||
getAll() {
|
||||
return this.http.get<Results<Location>>({ url: route('/locations') });
|
||||
}
|
||||
|
||||
async create(body: LocationCreate) {
|
||||
create(body: LocationCreate) {
|
||||
return this.http.post<LocationCreate, Location>({ url: route('/locations'), body });
|
||||
}
|
||||
|
||||
async get(id: string) {
|
||||
get(id: string) {
|
||||
return this.http.get<Location>({ url: route(`/locations/${id}`) });
|
||||
}
|
||||
async delete(id: string) {
|
||||
|
||||
delete(id: string) {
|
||||
return this.http.delete<void>({ url: route(`/locations/${id}`) });
|
||||
}
|
||||
|
||||
async update(id: string, body: LocationUpdate) {
|
||||
update(id: string, body: LocationUpdate) {
|
||||
return this.http.put<LocationUpdate, Location>({ url: route(`/locations/${id}`), body });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Requests } from '~~/lib/requests';
|
||||
import { BaseAPI, route } from './base';
|
||||
import { ItemsApi } from './classes/items';
|
||||
import { LabelsApi } from './classes/labels';
|
||||
import { LocationsApi } from './classes/locations';
|
||||
import { Requests } from '~~/lib/requests';
|
||||
|
||||
export type Result<T> = {
|
||||
item: T;
|
||||
|
|
|
@ -77,7 +77,7 @@ export class Requests {
|
|||
|
||||
const token = this.token();
|
||||
if (token !== '' && payload.headers !== undefined) {
|
||||
payload.headers['Authorization'] = token;
|
||||
payload.headers.Authorization = token;
|
||||
}
|
||||
|
||||
if (this.methodSupportsBody(method)) {
|
||||
|
|
|
@ -9,12 +9,12 @@ export default defineNuxtConfig({
|
|||
title: 'Homebox',
|
||||
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.svg' }],
|
||||
},
|
||||
outDir: '../backend/app/api/public',
|
||||
vite: {
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': 'http://localhost:7745',
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
},
|
||||
});
|
||||
|
|
|
@ -5,13 +5,25 @@
|
|||
"dev": "nuxt dev",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare",
|
||||
"lint": "eslint --ext \".ts,.js,.vue\" --ignore-path ../.gitignore .",
|
||||
"lint:fix": "eslint --ext \".ts,.js,.vue\" --ignore-path ../.gitignore . --fix",
|
||||
"test:ci": "TEST_SHUTDOWN_API_SERVER=true vitest --run --config ./test/vitest.config.ts",
|
||||
"test:local": "TEST_SHUTDOWN_API_SERVER=false && vitest --run --config ./test/vitest.config.ts",
|
||||
"test:watch": " TEST_SHUTDOWN_API_SERVER=false vitest --config ./test/vitest.config.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxtjs/eslint-config-typescript": "^11.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.36.2",
|
||||
"@typescript-eslint/parser": "^5.36.2",
|
||||
"eslint": "^8.23.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-vue": "^9.4.0",
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"nuxt": "3.0.0-rc.8",
|
||||
"prettier": "^2.7.1",
|
||||
"typescript": "^4.8.3",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vitest": "^0.22.1"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
useHead({
|
||||
title: "404. Not Found",
|
||||
});
|
||||
definePageMeta({
|
||||
layout: "404",
|
||||
});
|
||||
useHead({
|
||||
title: '404. Not Found',
|
||||
});
|
||||
definePageMeta({
|
||||
layout: '404',
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
|
||||
<section aria-labelledby="profile-overview-title" class="mt-8">
|
||||
<div class="overflow-hidden rounded-lg bg-white shadow">
|
||||
<h2 class="sr-only" id="profile-overview-title">Profile Overview</h2>
|
||||
<h2 id="profile-overview-title" class="sr-only">Profile Overview</h2>
|
||||
<div class="bg-white p-6">
|
||||
<div class="sm:flex sm:items-center sm:justify-between">
|
||||
<div class="sm:flex sm:space-x-5">
|
||||
|
@ -148,7 +148,7 @@
|
|||
<section>
|
||||
<BaseSectionHeader class="mb-5"> Storage Locations </BaseSectionHeader>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 card md:grid-cols-3 gap-4">
|
||||
<LocationCard v-for="location in locations" :location="location" />
|
||||
<LocationCard v-for="location in locations" :key="location.id" :location="location" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
@ -157,7 +157,7 @@
|
|||
Items
|
||||
<template #description>
|
||||
<div class="tooltip" data-tip="Import CSV File">
|
||||
<button @click="openDialog" class="btn btn-primary btn-sm">
|
||||
<button class="btn btn-primary btn-sm" @click="openDialog">
|
||||
<Icon name="mdi-database" class="mr-2"></Icon>
|
||||
Import
|
||||
</button>
|
||||
|
@ -165,14 +165,14 @@
|
|||
</template>
|
||||
</BaseSectionHeader>
|
||||
<div class="grid sm:grid-cols-2 gap-4">
|
||||
<ItemCard v-for="item in items" :item="item" />
|
||||
<ItemCard v-for="item in items" :key="item.id" :item="item" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<BaseSectionHeader class="mb-5"> Labels </BaseSectionHeader>
|
||||
<div class="flex gap-2 flex-wrap">
|
||||
<LabelChip v-for="label in labels" size="lg" :label="label" />
|
||||
<LabelChip v-for="label in labels" :key="label.id" size="lg" :label="label" />
|
||||
</div>
|
||||
</section>
|
||||
</BaseContainer>
|
||||
|
|
|
@ -161,9 +161,9 @@
|
|||
</h2>
|
||||
<TextField
|
||||
v-for="field in registerFields"
|
||||
:key="field.label"
|
||||
v-model="field.value"
|
||||
:label="field.label"
|
||||
:key="field.label"
|
||||
:type="field.type"
|
||||
/>
|
||||
<div class="card-actions justify-end">
|
||||
|
@ -188,9 +188,9 @@
|
|||
</h2>
|
||||
<TextField
|
||||
v-for="field in loginFields"
|
||||
:key="field.label"
|
||||
v-model="field.value"
|
||||
:label="field.label"
|
||||
:key="field.label"
|
||||
:type="field.type"
|
||||
/>
|
||||
<div class="card-actions justify-end mt-2">
|
||||
|
@ -204,8 +204,8 @@
|
|||
</Transition>
|
||||
<div class="text-center mt-6">
|
||||
<button
|
||||
@click="toggleLogin"
|
||||
class="text-base-content text-lg hover:bg-primary hover:text-primary-content px-3 py-1 rounded-xl transition-colors duration-200"
|
||||
@click="toggleLogin"
|
||||
>
|
||||
{{ registerForm ? 'Already a User? Login' : 'Not a User? Register' }}
|
||||
</button>
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
<h3 class="text-lg font-medium leading-6">Item Details</h3>
|
||||
</div>
|
||||
<div class="border-t border-gray-300 sm:p-0">
|
||||
<div class="sm:divide-y sm:divide-gray-300 grid grid-cols-1" v-for="field in mainFields">
|
||||
<div v-for="field in mainFields" :key="field.ref" class="sm:divide-y sm:divide-gray-300 grid grid-cols-1">
|
||||
<div class="pt-2 pb-4 sm:px-6 border-b border-gray-300">
|
||||
<FormTextArea v-if="field.type === 'textarea'" v-model="item[field.ref]" :label="field.label" inline />
|
||||
<FormTextField v-else-if="field.type === 'text'" v-model="item[field.ref]" :label="field.label" inline />
|
||||
|
@ -118,7 +118,7 @@
|
|||
<h3 class="text-lg font-medium leading-6">Purchase Details</h3>
|
||||
</div>
|
||||
<div class="border-t border-gray-300 sm:p-0">
|
||||
<div class="sm:divide-y sm:divide-gray-300 grid grid-cols-1" v-for="field in purchaseFields">
|
||||
<div v-for="field in purchaseFields" :key="field.ref" class="sm:divide-y sm:divide-gray-300 grid grid-cols-1">
|
||||
<div class="pt-2 pb-4 sm:px-6 border-b border-gray-300">
|
||||
<FormTextArea v-if="field.type === 'textarea'" v-model="item[field.ref]" :label="field.label" inline />
|
||||
<FormTextField v-else-if="field.type === 'text'" v-model="item[field.ref]" :label="field.label" inline />
|
||||
|
@ -133,7 +133,7 @@
|
|||
<h3 class="text-lg font-medium leading-6">Sold Details</h3>
|
||||
</div>
|
||||
<div class="border-t border-gray-300 sm:p-0">
|
||||
<div class="sm:divide-y sm:divide-gray-300 grid grid-cols-1" v-for="field in soldFields">
|
||||
<div v-for="field in soldFields" :key="field.ref" class="sm:divide-y sm:divide-gray-300 grid grid-cols-1">
|
||||
<div class="pt-2 pb-4 sm:px-6 border-b border-gray-300">
|
||||
<FormTextArea v-if="field.type === 'textarea'" v-model="item[field.ref]" :label="field.label" inline />
|
||||
<FormTextField v-else-if="field.type === 'text'" v-model="item[field.ref]" :label="field.label" inline />
|
||||
|
|
|
@ -118,11 +118,11 @@
|
|||
</span>
|
||||
<template #after>
|
||||
<div class="flex flex-wrap gap-3 mt-3">
|
||||
<LabelChip class="badge-primary" v-for="label in item.labels" :label="label"></LabelChip>
|
||||
<LabelChip v-for="label in item.labels" :key="label.id" class="badge-primary" :label="label" />
|
||||
</div>
|
||||
<div class="modal-action">
|
||||
<label class="label cursor-pointer mr-auto">
|
||||
<input type="checkbox" v-model="preferences.showEmpty" class="toggle toggle-primary" />
|
||||
<input v-model="preferences.showEmpty" type="checkbox" class="toggle toggle-primary" />
|
||||
<span class="label-text ml-4"> Show Empty </span>
|
||||
</label>
|
||||
<BaseButton size="sm" :to="`/item/${itemId}/edit`">
|
||||
|
@ -164,13 +164,13 @@
|
|||
</ul>
|
||||
</template>
|
||||
</BaseDetails>
|
||||
<BaseDetails :details="purchaseDetails" v-if="showPurchase">
|
||||
<BaseDetails v-if="showPurchase" :details="purchaseDetails">
|
||||
<template #title> Purchase Details </template>
|
||||
</BaseDetails>
|
||||
<BaseDetails :details="warrantyDetails" v-if="showWarranty">
|
||||
<BaseDetails v-if="showWarranty" :details="warrantyDetails">
|
||||
<template #title> Warranty </template>
|
||||
</BaseDetails>
|
||||
<BaseDetails :details="soldDetails" v-if="showSold">
|
||||
<BaseDetails v-if="showSold" :details="soldDetails">
|
||||
<template #title> Sold </template>
|
||||
</BaseDetails>
|
||||
</div>
|
||||
|
|
|
@ -32,62 +32,64 @@
|
|||
soldNotes: '',
|
||||
});
|
||||
|
||||
function submit() {}
|
||||
function submit() {
|
||||
console.log('Submitted!');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BaseContainer is="section">
|
||||
<BaseContainer cmp="section">
|
||||
<BaseSectionHeader> Add an Item To Your Inventory </BaseSectionHeader>
|
||||
<form @submit.prevent="submit" class="max-w-3xl mx-auto my-5 space-y-6">
|
||||
<form class="max-w-3xl mx-auto my-5 space-y-6" @submit.prevent="submit">
|
||||
<div class="divider collapse-title px-0 cursor-pointer">Required Information</div>
|
||||
<div class="bg-base-200 card">
|
||||
<div class="card-body">
|
||||
<FormTextField label="Name" v-model="form.name" />
|
||||
<FormTextArea label="Description" v-model="form.description" limit="1000" />
|
||||
<FormTextField v-model="form.name" label="Name" />
|
||||
<FormTextArea v-model="form.description" label="Description" limit="1000" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider">
|
||||
<button class="btn btn-sm" @click="show.identification = !show.identification">Product Information</button>
|
||||
</div>
|
||||
<div class="card bg-base-200" v-if="show.identification">
|
||||
<div v-if="show.identification" class="card bg-base-200">
|
||||
<div class="card-body grid md:grid-cols-2">
|
||||
<FormTextField label="Serial Number" v-model="form.serialNumber" />
|
||||
<FormTextField label="Model Number" v-model="form.modelNumber" />
|
||||
<FormTextField label="Manufacturer" v-model="form.manufacturer" />
|
||||
<FormTextField v-model="form.serialNumber" label="Serial Number" />
|
||||
<FormTextField v-model="form.modelNumber" label="Model Number" />
|
||||
<FormTextField v-model="form.manufacturer" label="Manufacturer" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<button class="btn btn-sm" @click="show.purchase = !show.purchase">Purchase Information</button>
|
||||
<div class="divider"></div>
|
||||
</div>
|
||||
<div class="card bg-base-200" v-if="show.purchase">
|
||||
<div v-if="show.purchase" class="card bg-base-200">
|
||||
<div class="card-body grid md:grid-cols-2">
|
||||
<FormTextField label="Purchase Time" v-model="form.purchaseTime" />
|
||||
<FormTextField label="Purchase Price" v-model="form.purchasePrice" />
|
||||
<FormTextField label="Purchase From" v-model="form.purchaseFrom" />
|
||||
<FormTextField v-model="form.purchaseTime" label="Purchase Time" />
|
||||
<FormTextField v-model="form.purchasePrice" label="Purchase Price" />
|
||||
<FormTextField v-model="form.purchaseFrom" label="Purchase From" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider">
|
||||
<button class="btn btn-sm" @click="show.sold = !show.sold">Sold Information</button>
|
||||
</div>
|
||||
<div class="card bg-base-200" v-if="show.sold">
|
||||
<div v-if="show.sold" class="card bg-base-200">
|
||||
<div class="card-body">
|
||||
<div class="grid md:grid-cols-2 gap-2">
|
||||
<FormTextField label="Sold Time" v-model="form.soldTime" />
|
||||
<FormTextField label="Sold Price" v-model="form.soldPrice" />
|
||||
<FormTextField label="Sold To" v-model="form.soldTo" />
|
||||
<FormTextField v-model="form.soldTime" label="Sold Time" />
|
||||
<FormTextField v-model="form.soldPrice" label="Sold Price" />
|
||||
<FormTextField v-model="form.soldTo" label="Sold To" />
|
||||
</div>
|
||||
<FormTextArea label="Sold Notes" v-model="form.soldNotes" limit="1000" />
|
||||
<FormTextArea v-model="form.soldNotes" label="Sold Notes" limit="1000" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider">
|
||||
<button class="btn btn-sm" @click="show.extras = !show.extras">Extras</button>
|
||||
</div>
|
||||
<div class="card bg-base-200" v-if="show.extras">
|
||||
<div v-if="show.extras" class="card bg-base-200">
|
||||
<div class="card-body">
|
||||
<FormTextArea label="Notes" v-model="form.notes" limit="1000" />
|
||||
<FormTextArea v-model="form.notes" label="Notes" limit="1000" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -103,8 +103,8 @@
|
|||
<BaseModal v-model="updateModal">
|
||||
<template #title> Update Label </template>
|
||||
<form v-if="label" @submit.prevent="update">
|
||||
<FormTextField :autofocus="true" label="Label Name" v-model="updateData.name" />
|
||||
<FormTextField label="Label Description" v-model="updateData.description" />
|
||||
<FormTextField v-model="updateData.name" :autofocus="true" label="Label Name" />
|
||||
<FormTextField v-model="updateData.description" label="Label Description" />
|
||||
<div class="modal-action">
|
||||
<BaseButton type="submit" :loading="updating"> Update </BaseButton>
|
||||
</div>
|
||||
|
@ -119,7 +119,7 @@
|
|||
</BaseDetails>
|
||||
<div class="form-control ml-auto mr-2 max-w-[130px]">
|
||||
<label class="label cursor-pointer">
|
||||
<input type="checkbox" v-model.checked="preferences.showDetails" class="checkbox" />
|
||||
<input v-model="preferences.showDetails" type="checkbox" class="toggle" />
|
||||
<span class="label-text"> Detailed View </span>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -129,7 +129,7 @@
|
|||
<section v-if="label">
|
||||
<BaseSectionHeader class="mb-5"> Items </BaseSectionHeader>
|
||||
<div class="grid gap-2 grid-cols-2">
|
||||
<ItemCard v-for="item in label.items" :item="item" :key="item.id" />
|
||||
<ItemCard v-for="item in label.items" :key="item.id" :item="item" />
|
||||
</div>
|
||||
</section>
|
||||
</BaseContainer>
|
||||
|
|
|
@ -102,8 +102,8 @@
|
|||
<BaseModal v-model="updateModal">
|
||||
<template #title> Update Location </template>
|
||||
<form v-if="location" @submit.prevent="update">
|
||||
<FormTextField :autofocus="true" label="Location Name" v-model="updateData.name" />
|
||||
<FormTextField label="Location Description" v-model="updateData.description" />
|
||||
<FormTextField v-model="updateData.name" :autofocus="true" label="Location Name" />
|
||||
<FormTextField v-model="updateData.description" label="Location Description" />
|
||||
<div class="modal-action">
|
||||
<BaseButton type="submit" :loading="updating"> Update </BaseButton>
|
||||
</div>
|
||||
|
@ -118,7 +118,7 @@
|
|||
</BaseDetails>
|
||||
<div class="form-control ml-auto mr-2 max-w-[130px]">
|
||||
<label class="label cursor-pointer">
|
||||
<input type="checkbox" v-model.checked="preferences.showDetails" class="checkbox" />
|
||||
<input v-model="preferences.showDetails" type="checkbox" class="toggle" />
|
||||
<span class="label-text"> Detailed View </span>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -128,7 +128,7 @@
|
|||
<section v-if="location">
|
||||
<BaseSectionHeader class="mb-5"> Items </BaseSectionHeader>
|
||||
<div class="grid gap-2 grid-cols-2">
|
||||
<ItemCard v-for="item in location.items" :item="item" :key="item.id" />
|
||||
<ItemCard v-for="item in location.items" :key="item.id" :item="item" />
|
||||
</div>
|
||||
</section>
|
||||
</BaseContainer>
|
||||
|
|
1413
frontend/pnpm-lock.yaml
generated
1413
frontend/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
@ -3,4 +3,4 @@ module.exports = {
|
|||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { UserApi } from '~~/lib/api/user';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useLocalStorage } from '@vueuse/core';
|
||||
import { UserApi } from '~~/lib/api/user';
|
||||
|
||||
export const useAuthStore = defineStore('auth', {
|
||||
state: () => ({
|
||||
|
|
|
@ -7,9 +7,5 @@ module.exports = {
|
|||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [
|
||||
require('@tailwindcss/aspect-ratio'),
|
||||
require('@tailwindcss/typography'),
|
||||
require('daisyui'),
|
||||
],
|
||||
plugins: [require('@tailwindcss/aspect-ratio'), require('@tailwindcss/typography'), require('daisyui')],
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
export const PORT = "7745";
|
||||
export const HOST = "http://127.0.0.1";
|
||||
export const BASE_URL = HOST + ":" + PORT;
|
||||
|
||||
export const PORT = '7745';
|
||||
export const HOST = 'http://127.0.0.1';
|
||||
export const BASE_URL = HOST + ':' + PORT;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/// <reference types="vitest" />
|
||||
import { defineConfig } from "vite";
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globalSetup: "./test/setup.ts",
|
||||
globalSetup: './test/setup.ts',
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue