Added 'Terms of Service' and 'Privacy policy' pages
This commit is contained in:
parent
0add58254d
commit
176665d7d4
14 changed files with 98 additions and 24 deletions
|
|
@ -58,8 +58,8 @@ const doLogin = async () => {
|
|||
</CardContent>
|
||||
</Card>
|
||||
<FieldDescription class="px-6 text-center">
|
||||
<NuxtLink to="/"><Button variant="link">Terms of Service</Button></NuxtLink>
|
||||
<NuxtLink to="/"><Button variant="link">Privacy Policy</Button></NuxtLink>
|
||||
<NuxtLink to="/legal/terms-of-service"><Button variant="link">Terms of Service</Button></NuxtLink>
|
||||
<NuxtLink to="/legal/privacy-policy"><Button variant="link">Privacy Policy</Button></NuxtLink>
|
||||
</FieldDescription>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ const createAccount = async () => {
|
|||
</Card>
|
||||
</ClientOnly>
|
||||
<FieldDescription class="px-6 text-center">
|
||||
<NuxtLink to="/"><Button variant="link">Terms of Service</Button></NuxtLink>
|
||||
<NuxtLink to="/"><Button variant="link">Privacy Policy</Button></NuxtLink>
|
||||
<NuxtLink to="/legal/terms-of-service"><Button variant="link">Terms of Service</Button></NuxtLink>
|
||||
<NuxtLink to="/legal/privacy-policy"><Button variant="link">Privacy Policy</Button></NuxtLink>
|
||||
</FieldDescription>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -8,12 +8,8 @@ import { SidebarInset, SidebarProvider, SidebarTrigger } from "~/components/ui/s
|
|||
|
||||
import { Separator } from "~/components/ui/separator";
|
||||
|
||||
import { useRuntimeConfig } from "#app";
|
||||
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
|
||||
const authStore = useAuthStore();
|
||||
await authStore.init();
|
||||
</script>
|
||||
|
|
@ -31,12 +27,8 @@ await authStore.init();
|
|||
<slot />
|
||||
</main>
|
||||
<footer class="flex h-12 shrink-0 items-center gap-2 border-b px-4" data-testid="footer">
|
||||
<div v-if="currentYear === 2025" class="bg-muted/50 flex-1 rounded-xl p-2 text-center">
|
||||
Glowing Fiesta 2025 <span class="text-muted-foreground">({{ config.public.appVersion }})</span>
|
||||
</div>
|
||||
<div v-else class="bg-muted/50 flex-1 rounded-xl p-2 text-center">
|
||||
Glowing Fiesta 2025 - {{ currentYear }} <span class="text-muted-foreground">({{ config.public.appVersion }})</span>
|
||||
</div>
|
||||
<div v-if="currentYear === 2025" class="bg-muted/50 flex-1 rounded-xl p-2 text-center">Glowing Fiesta 2025</div>
|
||||
<div v-else class="bg-muted/50 flex-1 rounded-xl p-2 text-center">Glowing Fiesta 2025 - {{ currentYear }}</div>
|
||||
</footer>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { BookOpen, ChevronRight, HandCoins, Settings2, SquareTerminal } from "lucide-vue-next";
|
||||
import { useRuntimeConfig } from "#app";
|
||||
import { BookOpen, BookOpenText, ChevronRight, HandCoins, Settings2, SquareTerminal } from "lucide-vue-next";
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
|
|
@ -53,6 +54,16 @@ const data = {
|
|||
{ title: "Changelog", url: "#" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Legal",
|
||||
url: "#",
|
||||
icon: BookOpenText,
|
||||
isActive: true,
|
||||
items: [
|
||||
{ title: "Terms of Service", url: "/legal/terms-of-service" },
|
||||
{ title: "Privacy Policy", url: "/legal/privacy-policy" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Settings",
|
||||
url: "#",
|
||||
|
|
@ -85,6 +96,8 @@ const props = withDefaults(defineProps<SidebarLayoutProps>(), {
|
|||
});
|
||||
|
||||
const navMain = computed(() => props.navItems || data.navMain);
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -101,7 +114,7 @@ const navMain = computed(() => props.navItems || data.navMain);
|
|||
</div>
|
||||
<div class="flex flex-col gap-0.5 leading-none">
|
||||
<span class="font-bold text-primary">Glowing Fiesta</span>
|
||||
<span>v1.0.0</span>
|
||||
<span>v{{ config.public.appVersion }}</span>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</SidebarMenuButton>
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ useSeoMeta({
|
|||
</Card>
|
||||
<FieldDescription class="px-6 text-center">
|
||||
<NuxtLink to="/"><Button variant="link">Home</Button></NuxtLink>
|
||||
<NuxtLink to="/"><Button variant="link">Terms of Service</Button></NuxtLink>
|
||||
<NuxtLink to="/"><Button variant="link">Privacy Policy</Button></NuxtLink>
|
||||
<NuxtLink to="/legal/terms-of-service"><Button variant="link">Terms of Service</Button></NuxtLink>
|
||||
<NuxtLink to="/legal/privacy-policy"><Button variant="link">Privacy Policy</Button></NuxtLink>
|
||||
</FieldDescription>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
22
app/pages/legal/privacy-policy.vue
Normal file
22
app/pages/legal/privacy-policy.vue
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { useRuntimeConfig, useSeoMeta } from "#app";
|
||||
import { useBreadcrumbStore } from "~/stores/breadcrumbs";
|
||||
|
||||
const breadcrumbStore = useBreadcrumbStore();
|
||||
breadcrumbStore.setBreadcrumbs([{ label: "Legal" }, { label: "Privacy Policy", to: "/legal/privacy-policy" }]);
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
useSeoMeta({
|
||||
title: "Privacy Policy",
|
||||
description: "Privacy Policy page of a very nice all-purpose application",
|
||||
ogTitle: "Privacy Policy",
|
||||
ogDescription: "Privacy Policy page of a very nice all-purpose application",
|
||||
ogImage: config.public.siteUrl + "/images/human.png",
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-muted/50 min-h-screen flex-1 rounded-xl md:min-h-min flex px-4 py-2 gap-2">
|
||||
<h1 class="text-2xl font-bold text-primary">Privacy Policy</h1>
|
||||
</div>
|
||||
</template>
|
||||
22
app/pages/legal/terms-of-service.vue
Normal file
22
app/pages/legal/terms-of-service.vue
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { useRuntimeConfig, useSeoMeta } from "#app";
|
||||
import { useBreadcrumbStore } from "~/stores/breadcrumbs";
|
||||
|
||||
const breadcrumbStore = useBreadcrumbStore();
|
||||
breadcrumbStore.setBreadcrumbs([{ label: "Legal" }, { label: "Terms of Service", to: "/legal/terms-of-service" }]);
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
useSeoMeta({
|
||||
title: "Terms of Service",
|
||||
description: "Terms of Service page of a very nice all-purpose application",
|
||||
ogTitle: "Terms of Service",
|
||||
ogDescription: "Terms of Service page of a very nice all-purpose application",
|
||||
ogImage: config.public.siteUrl + "/images/human.png",
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-muted/50 min-h-screen flex-1 rounded-xl md:min-h-min flex px-4 py-2 gap-2">
|
||||
<h1 class="text-2xl font-bold text-primary">Terms of Service</h1>
|
||||
</div>
|
||||
</template>
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "glowing-fiesta",
|
||||
"version": "0.0.0",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "glowing-fiesta",
|
||||
"version": "0.0.0",
|
||||
"version": "0.0.1",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@pinia/nuxt": "^0.11.3",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "glowing-fiesta",
|
||||
"version": "0.0.0",
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ describe("Default.vue", () => {
|
|||
});
|
||||
await flushPromises();
|
||||
const footer = wrapper.find("[data-testid='footer']");
|
||||
expect(footer.text()).toBe("Glowing Fiesta 2025 (1.0.1)");
|
||||
expect(footer.text()).toBe("Glowing Fiesta 2025");
|
||||
});
|
||||
|
||||
it("footer shows range when current year is not 2025", async () => {
|
||||
|
|
@ -75,7 +75,7 @@ describe("Default.vue", () => {
|
|||
});
|
||||
await flushPromises();
|
||||
const footer = wrapper.find("[data-testid='footer']");
|
||||
expect(footer.text()).toBe("Glowing Fiesta 2025 - 2069 (1.0.1)");
|
||||
expect(footer.text()).toBe("Glowing Fiesta 2025 - 2069");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { describe, expect, it, vi, beforeAll, afterAll } from "vitest";
|
|||
import SidebarLayout from "~/layouts/default/Sidebar.vue";
|
||||
import { ref } from "vue";
|
||||
import type * as SidebarUI from "~/components/ui/sidebar";
|
||||
import { useRuntimeConfig } from "#app";
|
||||
|
||||
const { useSidebarMock } = vi.hoisted(() => ({
|
||||
useSidebarMock: vi.fn(),
|
||||
|
|
@ -112,6 +113,7 @@ vi.mock("lucide-vue-next", () => {
|
|||
ChevronsUpDown: MockIcon,
|
||||
CreditCard: MockIcon,
|
||||
BookOpen: MockIcon,
|
||||
BookOpenText: MockIcon,
|
||||
HandCoins: MockIcon,
|
||||
LogIn: MockIcon,
|
||||
LogOut: MockIcon,
|
||||
|
|
@ -162,7 +164,7 @@ describe("SidebarLayout", () => {
|
|||
});
|
||||
await flushPromises();
|
||||
expect(wrapper.text()).toContain("Glowing Fiesta");
|
||||
expect(wrapper.text()).toContain("v1.0.0");
|
||||
expect(wrapper.text()).toContain(`v${useRuntimeConfig().public.appVersion as string}`);
|
||||
});
|
||||
|
||||
it("renders sidebar content correctly", async () => {
|
||||
|
|
|
|||
11
tests/pages/legal/privacy-policy.test.ts
Normal file
11
tests/pages/legal/privacy-policy.test.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { mount, type VueWrapper } from "@vue/test-utils";
|
||||
import PrivacyPolicyPage from "~/pages/legal/privacy-policy.vue";
|
||||
|
||||
describe("pages/legal/privacy-policy.vue", () => {
|
||||
it("loads without crashing", () => {
|
||||
const wrapper: VueWrapper = mount(PrivacyPolicyPage);
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain("Privacy Policy");
|
||||
});
|
||||
});
|
||||
11
tests/pages/legal/terms-of-service.test.ts
Normal file
11
tests/pages/legal/terms-of-service.test.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { mount, type VueWrapper } from "@vue/test-utils";
|
||||
import TermsOfServicePage from "~/pages/legal/terms-of-service.vue";
|
||||
|
||||
describe("pages/legal/terms-of-service.vue", () => {
|
||||
it("loads without crashing", () => {
|
||||
const wrapper: VueWrapper = mount(TermsOfServicePage);
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain("Terms of Service");
|
||||
});
|
||||
});
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
"@/*": ["./app/*"],
|
||||
"#shared": ["./shared"],
|
||||
"#shared/*": ["./shared/*"],
|
||||
"#app": ["./node_modules/nuxt/dist/app"],
|
||||
}
|
||||
},
|
||||
"include": ["./tests/**/*"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue