feat(frontend): Install nuxt-ui, eslint, prettier, reformat whole code

This commit is contained in:
2025-02-21 10:51:29 +01:00
parent e7557ce2e2
commit d6effcd1d5
16 changed files with 8131 additions and 2113 deletions

View File

@@ -0,0 +1,5 @@
# Ignore artifacts:
build
coverage
.nuxt
.output

View File

@@ -0,0 +1 @@
{}

View File

@@ -13,9 +13,11 @@
## Common errors
### better-auth/cli generate
```
Couldn't read your auth config. Error: Could not locate the bindings file. Tried:
```
**Solution:** I was able to resolve by running npx node-gyp rebuild in 'node_modules/better-sqlite3'
https://github.com/WiseLibs/better-sqlite3/issues/1320

View File

@@ -0,0 +1,8 @@
export default defineAppConfig({
ui: {
colors: {
primary: "green",
neutral: "zinc",
},
},
});

View File

@@ -1,6 +1,43 @@
<template>
<UApp>
<NuxtLoadingIndicator />
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</UApp>
</template>
<script setup lang="ts">
const colorMode = useColorMode();
const color = computed(() =>
colorMode.value === "dark" ? "#111827" : "white",
);
useHead({
meta: [
{ charset: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ key: "theme-color", name: "theme-color", content: color },
],
link: [{ rel: "icon", href: "/favicon.ico" }],
htmlAttrs: {
lang: "en",
},
});
const title = "LegalConsentHub";
const description =
"Das Tool für die Einführung von mitbestimmungspflichtigen digitalen Lösungen.";
useSeoMeta({
title,
description,
ogTitle: title,
ogDescription: description,
ogImage: "https://dashboard-template.nuxt.dev/social-card.png",
twitterImage: "https://dashboard-template.nuxt.dev/social-card.png",
twitterCard: "summary_large_image",
});
</script>

View File

@@ -0,0 +1,2 @@
@import "tailwindcss";
@import "@nuxt/ui-pro";

View File

@@ -9,7 +9,12 @@
<div class="form-group">
<label for="password-login">Passwort:</label>
<input type="password" id="password-login" v-model="password" required />
<input
type="password"
id="password-login"
v-model="password"
required
/>
</div>
<button type="submit">Login</button>
@@ -18,30 +23,33 @@
</template>
<script setup>
import { ref } from 'vue';
import { ref } from "vue";
const email = ref('');
const password = ref('');
const email = ref("");
const password = ref("");
const handleLogin = () => {
if (!email.value || !password.value) {
alert('Bitte alle Felder ausfüllen');
alert("Bitte alle Felder ausfüllen");
return;
}
authClient.signIn.email({
authClient.signIn.email(
{
email: email.value,
password: password.value
}, {
password: password.value,
},
{
onRequest: (ctx) => {
console.log("Sending login request", ctx)
console.log("Sending login request", ctx);
},
onSuccess: (ctx) => {
console.log("Successfully logged in!")
console.log("Successfully logged in!");
},
onError: (ctx) => {
console.log(ctx.error.message);
},
});
},
);
};
</script>

View File

@@ -19,7 +19,12 @@
<div class="form-group">
<label for="confirmPassword">Passwort bestätigen:</label>
<input type="password" id="confirmPassword" v-model="confirmPassword" required />
<input
type="password"
id="confirmPassword"
v-model="confirmPassword"
required
/>
</div>
<button type="submit">Registrieren</button>
@@ -28,37 +33,45 @@
</template>
<script setup>
import { ref } from 'vue';
import { ref } from "vue";
const username = ref('');
const email = ref('');
const password = ref('');
const confirmPassword = ref('');
const username = ref("");
const email = ref("");
const password = ref("");
const confirmPassword = ref("");
const handleRegister = () => {
if (!username.value || !email.value || !password.value || !confirmPassword.value) {
alert('Bitte alle Felder ausfüllen');
if (
!username.value ||
!email.value ||
!password.value ||
!confirmPassword.value
) {
alert("Bitte alle Felder ausfüllen");
return;
}
if (password.value !== confirmPassword.value) {
alert('Passwörter stimmen nicht überein');
alert("Passwörter stimmen nicht überein");
return;
}
authClient.signUp.email({
authClient.signUp.email(
{
email: email.value,
password: password.value,
name: username.value
}, {
name: username.value,
},
{
onRequest: (ctx) => {
console.log("Sending register request", ctx)
console.log("Sending register request", ctx);
},
onSuccess: (ctx) => {
console.log("Successfully registered!")
console.log("Successfully registered!");
},
onError: (ctx) => {
console.log(ctx.error.message);
},
});
},
);
};
</script>

24
legalconsenthub/error.vue Normal file
View File

@@ -0,0 +1,24 @@
<template>
<UApp>
<UError :error="error" />
</UApp>
</template>
<script setup lang="ts">
import type { NuxtError } from "#app";
defineProps<{
error: NuxtError;
}>();
useSeoMeta({
title: "Page not found",
description: "We are sorry but this page could not be found.",
});
useHead({
htmlAttrs: {
lang: "en",
},
});
</script>

View File

@@ -0,0 +1,13 @@
import withNuxt from "./.nuxt/eslint.config.mjs";
export default withNuxt();
// your custom flat configs go here, for example:
// {
// files: ['**/*.ts', '**/*.tsx'],
// rules: {
// 'no-console': 'off' // allow console.log in TypeScript files
// }
// },
// {
// ...
// }

View File

@@ -1,6 +1,160 @@
<template>
<slot/>
<UDashboardGroup>
<UDashboardSearch :groups="groups" />
<UDashboardSidebar
collapsible
resizable
class="bg-(--ui-bg-elevated)/25"
:ui="{ footer: 'lg:border-t lg:border-(--ui-border)' }"
>
<template #header="{ collapsed }">
<TeamsMenu :collapsed="collapsed" />
</template>
<template #default="{ collapsed }">
<UDashboardSearchButton
:collapsed="collapsed"
class="bg-transparent ring-(--ui-border)"
/>
<UNavigationMenu
:collapsed="collapsed"
:items="links[0]"
orientation="vertical"
/>
<UNavigationMenu
:collapsed="collapsed"
:items="links[1]"
orientation="vertical"
class="mt-auto"
/>
</template>
<template #footer="{ collapsed }">
<UserMenu :collapsed="collapsed" />
</template>
</UDashboardSidebar>
<slot />
<!-- <HelpSlideover /> -->
<NotificationsSlideover />
</UDashboardGroup>
</template>
<script setup lang="ts">
const route = useRoute();
const toast = useToast();
const links = [
[
{
label: "Home",
icon: "i-lucide-house",
to: "/",
},
{
label: "Inbox",
icon: "i-lucide-inbox",
to: "/inbox",
badge: "4",
},
{
label: "Customers",
icon: "i-lucide-users",
to: "/customers",
},
{
label: "Settings",
to: "/settings",
icon: "i-lucide-settings",
defaultOpen: true,
children: [
{
label: "General",
to: "/settings",
exact: true,
},
{
label: "Members",
to: "/settings/members",
},
{
label: "Notifications",
to: "/settings/notifications",
},
{
label: "Security",
to: "/settings/security",
},
],
},
],
[
{
label: "Feedback",
icon: "i-lucide-message-circle",
to: "https://github.com/nuxt-ui-pro/dashboard",
target: "_blank",
},
{
label: "Help & Support",
icon: "i-lucide-info",
to: "https://github.com/nuxt/ui-pro",
target: "_blank",
},
],
];
const groups = computed(() => [
{
id: "links",
label: "Go to",
items: links.flat(),
},
{
id: "code",
label: "Code",
items: [
{
id: "source",
label: "View page source",
icon: "i-simple-icons-github",
to: `https://github.com/nuxt-ui-pro/dashboard/blob/v3/app/pages${route.path === "/" ? "/index" : route.path}.vue`,
target: "_blank",
},
],
},
]);
onMounted(async () => {
const cookie = useCookie("cookie-consent");
if (cookie.value === "accepted") {
return;
}
toast.add({
title:
"We use first-party cookies to enhance your experience on our website.",
duration: 0,
close: false,
actions: [
{
label: "Accept",
color: "neutral",
variant: "outline",
onClick: () => {
cookie.value = "accepted";
},
},
{
label: "Opt out",
color: "neutral",
variant: "ghost",
},
],
});
});
</script>

View File

@@ -1,4 +1,6 @@
export default defineNuxtConfig({
modules: ["@nuxt/ui-pro", "@nuxt/eslint"],
css: ["~/assets/css/main.css"],
devtools: { enabled: true },
compatibilityDate: '2024-11-01'
})
compatibilityDate: "2024-11-01",
});

View File

@@ -8,9 +8,13 @@
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
"format": "prettier . --write",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"fix:bettersqlite": "cd node_modules/better-sqlite3 && npx node-gyp rebuild && cd ../.."
},
"dependencies": {
"@nuxt/ui-pro": "3.0.0-alpha.13",
"better-auth": "^1.1.16",
"better-sqlite3": "^11.8.1",
"nuxt": "^3.15.4",
@@ -18,6 +22,10 @@
"vue-router": "latest"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.12"
"@nuxt/eslint": "^1.1.0",
"@types/better-sqlite3": "^7.6.12",
"eslint": "^9.20.1",
"prettier": "3.5.1",
"typescript": "^5.7.3"
}
}

View File

@@ -1,16 +1,75 @@
<template>
<UDashboardPanel id="home">
<template #header>
<UDashboardNavbar title="Home" :ui="{ right: 'gap-3' }">
<template #leading>
<UDashboardSidebarCollapse />
</template>
<template #right>
<UTooltip text="Notifications" :shortcuts="['N']">
<UButton color="neutral" variant="ghost" square>
<UChip color="error" inset>
<UIcon name="i-lucide-bell" class="size-5 shrink-0" />
</UChip>
</UButton>
</UTooltip>
<UDropdownMenu :items="items">
<UButton icon="i-lucide-plus" size="md" class="rounded-full" />
</UDropdownMenu>
</template>
</UDashboardNavbar>
<UDashboardToolbar>
<template #left>
<!-- NOTE: The `-ms-1` class is used to align with the `DashboardSidebarCollapse` button here. -->
<HomeDateRangePicker v-model="range" class="-ms-1" />
<HomePeriodSelect v-model="period" :range="range" />
</template>
</UDashboardToolbar>
</template>
<template #body>
<div>
<pre>{{ session }}</pre>
<h1>{{ session.data ? "Du bist eingeloggt" : "Nicht eingeloggt"}}</h1>
<h1>{{ session.data ? "Du bist eingeloggt" : "Nicht eingeloggt" }}</h1>
<button v-if="session?.data" @click="authClient.signOut()">
Sign out
</button>
</div>
<Register />
<Login />
<HomeStats :period="period" :range="range" />
<HomeChart :period="period" :range="range" />
<HomeSales :period="period" :range="range" />
</template>
</UDashboardPanel>
</template>
<script setup lang="ts">
const session = authClient.useSession();
const session = authClient.useSession()
const items = [
[
{
label: "New mail",
icon: "i-lucide-send",
to: "/inbox",
},
{
label: "New customer",
icon: "i-lucide-user-plus",
to: "/customers",
},
],
];
const range = shallowRef({
start: new Date(),
end: new Date(),
});
const period = ref<string>("daily");
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
import { auth } from "../../utils/auth";
import {H3Event} from "h3";
import { H3Event } from "h3";
export default defineEventHandler((event: H3Event) => {
return auth.handler(toWebRequest(event));