move to nuxt

This commit is contained in:
Hayden 2022-09-01 14:32:03 -08:00
parent 890eb55d27
commit 26ecb5a9d4
93 changed files with 5273 additions and 4749 deletions

View file

@ -0,0 +1,23 @@
import { PublicApi } from "~~/lib/api/public";
import { UserApi } from "~~/lib/api/user";
import { Requests } from "~~/lib/requests";
import { useAuthStore } from "~~/stores/auth";
async function ApiDebugger(r: Response) {
console.table({
"Request Url": r.url,
"Response Status": r.status,
"Response Status Text": r.statusText,
});
}
export function usePublicApi(): PublicApi {
const requests = new Requests("", "", {}, ApiDebugger);
return new PublicApi(requests);
}
export function useUserApi(): UserApi {
const authStore = useAuthStore();
const requests = new Requests("", () => authStore.token, {}, ApiDebugger);
return new UserApi(requests);
}

View file

@ -0,0 +1,40 @@
import { UseConfirmDialogReturn } from '@vueuse/core';
import { Ref } from 'vue';
type Store = UseConfirmDialogReturn<any, Boolean, Boolean> & {
text: Ref<string>;
setup: boolean;
};
const store: Partial<Store> = {
text: ref('Are you sure you want to delete this item? '),
setup: false,
};
/**
* This function is used to wrap the ModalConfirmation which is a "Singleton" component
* that is used to confirm actions. It's mounded once on the root of the page and reused
* for every confirmation action that is required.
*
* This is in an experimental phase of development and may have unknown or unexpected side effects.
*/
export function useConfirm(): Store {
if (!store.setup) {
store.setup = true;
const { isRevealed, reveal, confirm, cancel } = useConfirmDialog<any, Boolean, Boolean>();
store.isRevealed = isRevealed;
store.reveal = reveal;
store.confirm = confirm;
store.cancel = cancel;
}
async function openDialog(msg: string) {
store.text.value = msg;
return await store.reveal();
}
return {
...(store as Store),
reveal: openDialog,
};
}

31
frontend/composables/use-ids.ts Executable file
View file

@ -0,0 +1,31 @@
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();
}

View file

@ -0,0 +1,57 @@
import { useId } from './use-ids';
interface Notification {
id: string;
message: string;
type: 'success' | 'error' | 'info';
}
const notifications = ref<Notification[]>([]);
function addNotification(notification: 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);
}
}
export function useNotifications() {
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',
});
},
};
}

View file

@ -0,0 +1,23 @@
import { Ref } from 'vue';
export type LocationViewPreferences = {
showDetails: boolean;
};
/**
* useLocationViewPreferences loads the view preferences from local storage and hydrates
* them. These are reactive and will update the local storage when changed.
*/
export function useLocationViewPreferences(): Ref<LocationViewPreferences> {
const results = useLocalStorage(
'homebox/preferences/location',
{
showDetails: true,
},
{ mergeDefaults: true }
);
// casting is required because the type returned is removable, however since we
// use `mergeDefaults` the result _should_ always be present.
return results as unknown as Ref<LocationViewPreferences>;
}