feat: setup monorepo for static frontend app (vdn-static)
34
apps/vdn-static/package.json
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "@repo/vdn-static",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vue-tsc -b && vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@tailwindcss/vite": "^4.1.6",
|
||||||
|
"@types/node": "^22.15.17",
|
||||||
|
"bulma": "^1.0.4",
|
||||||
|
"tailwindcss": "^4.1.6",
|
||||||
|
"vue": "^3.5.13",
|
||||||
|
"vue-i18n": "^11.1.3",
|
||||||
|
"vue-router": "^4.5.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
|
"@vue/tsconfig": "^0.7.0",
|
||||||
|
"eslint": "^9.26.0",
|
||||||
|
"eslint-plugin-vue": "^10.1.0",
|
||||||
|
"prettier": "^3.5.3",
|
||||||
|
"sass": "^1.87.0",
|
||||||
|
"typescript": "~5.8.3",
|
||||||
|
"typescript-eslint": "^8.32.1",
|
||||||
|
"unplugin-vue-router": "^0.12.0",
|
||||||
|
"vite": "^6.3.5",
|
||||||
|
"vue-tsc": "^2.2.8"
|
||||||
|
},
|
||||||
|
"packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
|
||||||
|
}
|
||||||
49
apps/vdn-static/src/App.vue
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import "./assets/style.scss";
|
||||||
|
import { ref, type Ref } from "vue";
|
||||||
|
|
||||||
|
const burgerOpen: Ref<boolean> = ref<boolean>(false);
|
||||||
|
|
||||||
|
const toggleBurger = (): void => {
|
||||||
|
burgerOpen.value = !burgerOpen.value;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="min-h-screen flex flex-col">
|
||||||
|
<!-- Main application wrapper -->
|
||||||
|
<nav
|
||||||
|
class="navbar is-fixed-top"
|
||||||
|
role="navigation"
|
||||||
|
aria-label="main navigation">
|
||||||
|
<div class="navbar-brand">
|
||||||
|
<RouterLink class="navbar-item has-text-weight-bold" to="/"
|
||||||
|
><img src="@/assets/ViossaFlagRect.svg" alt=""
|
||||||
|
/></RouterLink>
|
||||||
|
|
||||||
|
<div class="navbar-item">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
@click="toggleBurger()"
|
||||||
|
:class="`button is-link is-hoverable is-hidden-desktop ${burgerOpen ? 'is-active' : ''}`"
|
||||||
|
aria-label="menu"
|
||||||
|
:aria-expanded="`${burgerOpen ? 'true' : 'false'}`">
|
||||||
|
<span class="bx bx-burger"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div :class="`navbar-menu ${burgerOpen ? 'is-active' : ''}`">
|
||||||
|
<div class="navbar-start">
|
||||||
|
<RouterLink class="navbar-item" to="/"
|
||||||
|
>What is Viossa?</RouterLink
|
||||||
|
>
|
||||||
|
<RouterLink class="navbar-item" to="/resources"
|
||||||
|
>Resources</RouterLink
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<RouterView />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 496 B After Width: | Height: | Size: 496 B |
|
|
@ -0,0 +1,37 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps<{
|
||||||
|
title: string;
|
||||||
|
text: string;
|
||||||
|
image?: string;
|
||||||
|
alt?: string;
|
||||||
|
reverse: boolean;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="box my-5 px-4 py-3 columns is-vcentered">
|
||||||
|
<template v-if="reverse">
|
||||||
|
<div class="column">
|
||||||
|
<h2 class="title is-4">{{ title }}</h2>
|
||||||
|
<p class="has-text-white">{{ text }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="column is-one-quarter" v-if="image">
|
||||||
|
<figure class="image">
|
||||||
|
<img :src="image" :alt="alt" :title="alt" />
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
|
<div class="column is-one-quarter" v-if="image">
|
||||||
|
<figure class="image">
|
||||||
|
<img :src="image" :alt="alt" :title="alt" />
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<h2 class="title is-4">{{ title }}</h2>
|
||||||
|
<p class="has-text-white">{{ text }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
47
apps/vdn-static/src/components/pages/HomePage.vue
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import HomeSectionWrapper from "@/components/molecules/HomeSectionWrapper.vue";
|
||||||
|
import "@/assets/style.scss";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import type { MessageSchema } from "@/i18n/types";
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
const { tm } = useI18n();
|
||||||
|
const sectionList = computed<MessageSchema["sections"]>(() => tm("sections"));
|
||||||
|
const sectionsWithImages = computed(() =>
|
||||||
|
sectionList.value.map((section) => {
|
||||||
|
if (!section.image) return section;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...section,
|
||||||
|
image: new URL(`../../assets/${section.image}`, import.meta.url)
|
||||||
|
.href,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(sectionList.value);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<section class="hero is-primary">
|
||||||
|
<div class="hero-body">
|
||||||
|
<div class="title">BRÅTULA VIOSSA.NET MÅDE</div>
|
||||||
|
<div class="subtitle">
|
||||||
|
Hadjiplas per lera para Viossa – glossa fu vi
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section container">
|
||||||
|
<HomeSectionWrapper
|
||||||
|
v-for="(section, index) in sectionsWithImages"
|
||||||
|
:key="index"
|
||||||
|
:title="section.title"
|
||||||
|
:text="section.text"
|
||||||
|
:image="section.image"
|
||||||
|
:alt="section.alt"
|
||||||
|
:reverse="index % 2 !== 0" />
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
46
apps/vdn-static/src/components/pages/ResourcesPage.vue
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import LearningResourceWrapper from "@/components/molecules/LearningResourceWrapper.vue";
|
||||||
|
import "@/assets/style.scss";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import type { MessageSchema } from "@/i18n/types";
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
const { tm } = useI18n();
|
||||||
|
const resourceList = computed<MessageSchema["resources"]>(() =>
|
||||||
|
tm("resources"),
|
||||||
|
);
|
||||||
|
const resourcesWithImages = computed(() =>
|
||||||
|
resourceList.value.map((resource) => {
|
||||||
|
if (!resource.image) return resource;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...resource,
|
||||||
|
image: new URL(`../../assets/${resource.image}`, import.meta.url)
|
||||||
|
.href,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<section class="section">
|
||||||
|
<h1 class="title">Learning Resources</h1>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section container">
|
||||||
|
<LearningResourceWrapper
|
||||||
|
v-for="(resource, index) in resourcesWithImages"
|
||||||
|
:key="index"
|
||||||
|
:title="resource.title"
|
||||||
|
:subtitle="resource.subtitle"
|
||||||
|
:desc="resource.desc"
|
||||||
|
:link="resource.link"
|
||||||
|
:rulesLink="resource.rulesLink"
|
||||||
|
:image="resource.image"
|
||||||
|
:alt="resource.alt"
|
||||||
|
:joinText="resource.joinText"
|
||||||
|
:rulesText="resource.rulesText" />
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
17
apps/vdn-static/src/i18n/index.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { createI18n } from "vue-i18n";
|
||||||
|
import en_US from "../locales/en_US";
|
||||||
|
import vp_VL from "../locales/vp_VL";
|
||||||
|
import type { MessageSchema } from "./types";
|
||||||
|
|
||||||
|
const locales = { en_US, vp_VL } as const;
|
||||||
|
|
||||||
|
export type Locale = keyof typeof locales;
|
||||||
|
|
||||||
|
const i18n = createI18n<[MessageSchema], Locale>({
|
||||||
|
legacy: false,
|
||||||
|
locale: "vp_VL" satisfies Locale,
|
||||||
|
fallbackLocale: "en_US" satisfies Locale,
|
||||||
|
messages: locales,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default i18n;
|
||||||
8
apps/vdn-static/src/i18n/types.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import en_US from "../locales/en_US";
|
||||||
|
export interface MessageSchema extends Broaden<typeof en_US> {}
|
||||||
|
|
||||||
|
type Broaden<T> = {
|
||||||
|
[K in keyof T]: T[K] extends object ? Broaden<T[K]>
|
||||||
|
: T[K] extends string ? string
|
||||||
|
: T[K];
|
||||||
|
} & {};
|
||||||
33
apps/vdn-static/src/locales/en_US.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
export default {
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
title: "What is Viossa?",
|
||||||
|
text: "Viossa is a community-created artificial pidgin language, created to simulate the formation of natural pidgin languages. Viossa is characterized by its lack of standardization, with each speaker developing a personal idiolect. Spelling and pronunciation can vary greatly, and serve as a form of personal self-expression. Viossa is learnt and taught entirely by immersion — translation is prohibited while learning.",
|
||||||
|
image: "flakka.png",
|
||||||
|
alt: "Flag of the Viossa Language",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "History of Viossa",
|
||||||
|
text: "Viossa began as a Skype group in 2014, created by members of the r/conlangs community on Reddit, as an experiment to simulate the formation of a pidgin language. Pidgins are simplified languages resulting from contact between populations with no shared common language. Unlike most pidgins, which usually have two to three contributor languages, Viossa comes from many diverse languages. This is because people from all around the world helped to contribute to Viossa's vocabulary.",
|
||||||
|
image: "flakka.png",
|
||||||
|
alt: "Flag of the Viossa Language",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Community",
|
||||||
|
text: "The Viossa community is rich and colourful, drawing from many global traditions due to its worldwide online membership. Since the teaching culture puts an emphasis on linguistic immersion, and discourages prescriptivism, the culture of Viossa is as diverse and varied as the language and the people who speak it. For many, their personal dialect is a key form of identity and expression. The fluid nature of Viossa and lack of defined meanings makes Viossa popular for creative purposes, such as poetry and songwriting.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
resources: [
|
||||||
|
{
|
||||||
|
title: "Discord Server",
|
||||||
|
subtitle: "This is where most of the action happens! Hop on in!",
|
||||||
|
desc: "Originally started in 2015 something something read the rules here, then click the link below to join!",
|
||||||
|
link: "https://discord.gg/g3mG2gYjZD",
|
||||||
|
rulesLink: "https://viossadiskordserver.github.io/rules",
|
||||||
|
image: "discord.png",
|
||||||
|
alt: "Discord logo",
|
||||||
|
joinText: "Join",
|
||||||
|
rulesText: "Rules",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
35
apps/vdn-static/src/locales/vp_VL.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import type { MessageSchema } from "@/i18n/types";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
title: "Kafaen afto Viossa",
|
||||||
|
text: "Viossa tte glossa mahena grun vi nai vil fshtojena na bakadjin, grun vi svinnur ja! De aldjin zovti lera ne",
|
||||||
|
image: "flakka.png",
|
||||||
|
alt: "Flag of the Viossa Language",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "History of Viossa",
|
||||||
|
text: "Viossa began as a Skype group in 2014, created by members of the r/conlangs community on Reddit, as an experiment to simulate the formation of a pidgin language. Pidgins are simplified languages resulting from contact between populations with no shared common language. Unlike most pidgins, which usually have two to three contributor languages, Viossa comes from many diverse languages. This is because people from all around the world helped to contribute to Viossa's vocabulary.",
|
||||||
|
image: "flakka.png",
|
||||||
|
alt: "Flag of the Viossa Language",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Community",
|
||||||
|
text: "The Viossa community is rich and colourful, drawing from many global traditions due to its worldwide online membership. Since the teaching culture puts an emphasis on linguistic immersion, and discourages prescriptivism, the culture of Viossa is as diverse and varied as the language and the people who speak it. For many, their personal dialect is a key form of identity and expression. The fluid nature of Viossa and lack of defined meanings makes Viossa popular for creative purposes, such as poetry and songwriting.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
resources: [
|
||||||
|
{
|
||||||
|
title: "Discord Server",
|
||||||
|
subtitle: "This is where most of the action happens! Hop on in!",
|
||||||
|
desc: "Originally started in 2015 something something read the rules here, then click the link below to join!",
|
||||||
|
link: "https://discord.gg/g3mG2gYjZD",
|
||||||
|
rulesLink: "https://viossadiskordserver.github.io/rules",
|
||||||
|
image: "discord.png",
|
||||||
|
alt: "Discord logo",
|
||||||
|
joinText: "Join",
|
||||||
|
rulesText: "Rules",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as const satisfies MessageSchema;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import router from "./routes"
|
import router from "./routes";
|
||||||
import i18n from './i18n'
|
import i18n from "./i18n";
|
||||||
|
|
||||||
createApp(App).use(i18n).use(router).mount("#app");
|
createApp(App).use(i18n).use(router).mount("#app");
|
||||||
19
apps/vdn-static/src/routes/index.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
|
import type { RouteRecordRaw } from "vue-router";
|
||||||
|
|
||||||
|
import HomePage from "@/components/pages/HomePage.vue";
|
||||||
|
import ResourcesPage from "@/components/pages/ResourcesPage.vue";
|
||||||
|
|
||||||
|
const routes: RouteRecordRaw[] = [
|
||||||
|
{ path: "/", name: "Home", component: HomePage },
|
||||||
|
{ path: "/resources", name: "Resources", component: ResourcesPage },
|
||||||
|
// {
|
||||||
|
// path: '/:pathMatch(.*)*', // Vue Router 4 catch-all for 404s
|
||||||
|
// name: 'NotFound',
|
||||||
|
// component: NotFoundPage,
|
||||||
|
// },
|
||||||
|
];
|
||||||
|
|
||||||
|
const router = createRouter({ history: createWebHistory(), routes });
|
||||||
|
|
||||||
|
export default router;
|
||||||
|
|
@ -10,14 +10,16 @@
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noUncheckedSideEffectImports": true,
|
"noUncheckedSideEffectImports": true,
|
||||||
"noUncheckedIndexedAccess": true,
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["src/*"]
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts",
|
"src"
|
||||||
"src/**/*.tsx",
|
|
||||||
"src/**/*.vue",
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -19,7 +19,8 @@
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"erasableSyntaxOnly": true,
|
"erasableSyntaxOnly": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noUncheckedSideEffectImports": true
|
"noUncheckedSideEffectImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"vite.config.ts"
|
"vite.config.ts"
|
||||||
8
apps/vdn-static/vite.config.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import path from "path";
|
||||||
|
import { defineConfig } from "vite";
|
||||||
|
import vue from "@vitejs/plugin-vue";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [vue({})],
|
||||||
|
resolve: { alias: { "@": path.resolve(import.meta.dirname, "src") } },
|
||||||
|
});
|
||||||
33
package.json
|
|
@ -1,33 +0,0 @@
|
||||||
{
|
|
||||||
"name": "viossa.net",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "vue-tsc -b && vite build",
|
|
||||||
"preview": "vite preview"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@tailwindcss/vite": "^4.1.6",
|
|
||||||
"@types/node": "^22.15.17",
|
|
||||||
"bulma": "^1.0.4",
|
|
||||||
"tailwindcss": "^4.1.6",
|
|
||||||
"vue": "^3.5.13",
|
|
||||||
"vue-i18n": "^11.1.3",
|
|
||||||
"vue-router": "^4.5.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
|
||||||
"@vue/tsconfig": "^0.7.0",
|
|
||||||
"eslint": "^9.26.0",
|
|
||||||
"eslint-plugin-vue": "^10.1.0",
|
|
||||||
"prettier": "^3.5.3",
|
|
||||||
"sass": "^1.87.0",
|
|
||||||
"typescript": "~5.8.3",
|
|
||||||
"typescript-eslint": "^8.32.1",
|
|
||||||
"unplugin-vue-router": "^0.12.0",
|
|
||||||
"vite": "^6.3.5",
|
|
||||||
"vue-tsc": "^2.2.8"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2854
pnpm-lock.yaml
generated
Normal file
7
pnpm-workspace.yaml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
packages:
|
||||||
|
- apps/**
|
||||||
|
- libs/**
|
||||||
|
onlyBuiltDependencies:
|
||||||
|
- '@parcel/watcher'
|
||||||
|
- '@tailwindcss/oxide'
|
||||||
|
- esbuild
|
||||||
40
src/App.vue
|
|
@ -1,40 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="min-h-screen flex flex-col "><!-- Main application wrapper -->
|
|
||||||
<nav class="navbar is-fixed-top" role="navigation" aria-label="main navigation">
|
|
||||||
|
|
||||||
<div class="navbar-brand">
|
|
||||||
<RouterLink class="navbar-item has-text-weight-bold" to="/"><img src="@/assets/ViossaFlagRect.svg" alt=""/></RouterLink>
|
|
||||||
|
|
||||||
<div class="navbar-item">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
@click="toggleBurger()"
|
|
||||||
:class="`button is-link is-hoverable is-hidden-desktop ${burgerOpen ? 'is-active' : ''}`" aria-label="menu"
|
|
||||||
:aria-expanded="`${burgerOpen ? 'true' : 'false'}`">
|
|
||||||
<span class="bx bx-burger"></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div :class="`navbar-menu ${burgerOpen ? 'is-active' : ''}`">
|
|
||||||
<div class="navbar-start">
|
|
||||||
<RouterLink class="navbar-item" to="/">What is Viossa?</RouterLink>
|
|
||||||
<RouterLink class="navbar-item" to="/resources">Resources</RouterLink>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<RouterView />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import './assets/style.scss'
|
|
||||||
import { ref, type Ref } from 'vue'
|
|
||||||
|
|
||||||
const burgerOpen: Ref<Boolean> = ref<Boolean>(false);
|
|
||||||
|
|
||||||
function toggleBurger(): void {
|
|
||||||
burgerOpen.value = !burgerOpen.value;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="box my-5 px-4 py-3 columns is-vcentered">
|
|
||||||
|
|
||||||
<template v-if="reverse">
|
|
||||||
<div class="column">
|
|
||||||
<h2 class="title is-4">{{ title }}</h2>
|
|
||||||
<p class="has-text-white">{{ text }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="column is-one-quarter" v-if="image">
|
|
||||||
<figure class="image">
|
|
||||||
<img :src="image" :alt="alt" :title="alt" />
|
|
||||||
</figure>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-else>
|
|
||||||
<div class="column is-one-quarter" v-if="image">
|
|
||||||
<figure class="image">
|
|
||||||
<img :src="image" :alt="alt" :title="alt" />
|
|
||||||
</figure>
|
|
||||||
</div>
|
|
||||||
<div class="column">
|
|
||||||
<h2 class="title is-4">{{ title }}</h2>
|
|
||||||
<p class="has-text-white">{{ text }}</p>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
defineProps({
|
|
||||||
title: String,
|
|
||||||
text: String,
|
|
||||||
image: { type: String, required: false },
|
|
||||||
alt: { type: String, required: false },
|
|
||||||
reverse: Boolean,
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<section class="hero is-primary">
|
|
||||||
<div class="hero-body">
|
|
||||||
<div class="title">BRÅTULA VIOSSA.NET MÅDE</div>
|
|
||||||
<div class="subtitle">Hadjiplas per lera para Viossa – glossa fu vi</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="section container">
|
|
||||||
<HomeSectionWrapper
|
|
||||||
v-for="(section, index) in sectionsWithImages"
|
|
||||||
:key="index"
|
|
||||||
:title="section.title"
|
|
||||||
:text="section.text"
|
|
||||||
:image="section.image"
|
|
||||||
:alt="section.alt"
|
|
||||||
:reverse="index % 2 !== 0"
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import HomeSectionWrapper from '@/components/molecules/HomeSectionWrapper.vue'
|
|
||||||
import '@/assets/style.scss'
|
|
||||||
import { useI18n } from 'vue-i18n'
|
|
||||||
import type { MessageSchema } from '@/i18n/types'
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
const { tm } = useI18n()
|
|
||||||
const sectionList = computed<MessageSchema['sections']>(() => tm('sections'))
|
|
||||||
const sectionsWithImages = computed(() =>
|
|
||||||
sectionList.value.map(section => {
|
|
||||||
if (!section.image) return section
|
|
||||||
|
|
||||||
return {
|
|
||||||
...section,
|
|
||||||
image: new URL(`../../assets/${section.image}`, import.meta.url).href
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
console.log(sectionList.value)
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<section class="section">
|
|
||||||
<h1 class="title">Learning Resources</h1>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="section container">
|
|
||||||
<LearningResourceWrapper
|
|
||||||
v-for="(resource, index) in resourcesWithImages"
|
|
||||||
:key="index"
|
|
||||||
:title="resource.title"
|
|
||||||
:subtitle="resource.subtitle"
|
|
||||||
:desc="resource.desc"
|
|
||||||
:link="resource.link"
|
|
||||||
:rulesLink="resource.rulesLink"
|
|
||||||
:image="resource.image"
|
|
||||||
:alt="resource.alt"
|
|
||||||
:joinText="resource.joinText"
|
|
||||||
:rulesText="resource.rulesText"
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import LearningResourceWrapper from '@/components/molecules/LearningResourceWrapper.vue'
|
|
||||||
import '@/assets/style.scss'
|
|
||||||
import { useI18n } from 'vue-i18n'
|
|
||||||
import type { MessageSchema } from '@/i18n/types'
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
const { tm } = useI18n()
|
|
||||||
const resourceList = computed<MessageSchema['resources']>(() => tm('resources'))
|
|
||||||
const resourcesWithImages = computed(() =>
|
|
||||||
resourceList.value.map(resource => {
|
|
||||||
if (!resource.image) return resource
|
|
||||||
|
|
||||||
return {
|
|
||||||
...resource,
|
|
||||||
image: new URL(`../../assets/${resource.image}`, import.meta.url).href
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
import { createI18n } from 'vue-i18n'
|
|
||||||
import en_US from '../locales/en_US'
|
|
||||||
import vp_VL from '../locales/vp_VL'
|
|
||||||
import type { MessageSchema } from './types'
|
|
||||||
|
|
||||||
const i18n = createI18n<[MessageSchema], 'en_US' | 'vp_VL'>({
|
|
||||||
legacy: false,
|
|
||||||
locale: 'vp_VL',
|
|
||||||
fallbackLocale: 'en_US',
|
|
||||||
messages: {
|
|
||||||
en_US,
|
|
||||||
vp_VL
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default i18n
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
import en_US from '../locales/en_US'
|
|
||||||
export type MessageSchema = typeof en_US
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
export default {
|
|
||||||
"sections": [
|
|
||||||
{
|
|
||||||
"title": "What is Viossa?",
|
|
||||||
"text": "Viossa is a community-created artificial pidgin language, created to simulate the formation of natural pidgin languages. Viossa is characterized by its lack of standardization, with each speaker developing a personal idiolect. Spelling and pronunciation can vary greatly, and serve as a form of personal self-expression. Viossa is learnt and taught entirely by immersion — translation is prohibited while learning.",
|
|
||||||
"image": "flakka.png",
|
|
||||||
"alt": "Flag of the Viossa Language"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "History of Viossa",
|
|
||||||
"text": "Viossa began as a Skype group in 2014, created by members of the r/conlangs community on Reddit, as an experiment to simulate the formation of a pidgin language. Pidgins are simplified languages resulting from contact between populations with no shared common language. Unlike most pidgins, which usually have two to three contributor languages, Viossa comes from many diverse languages. This is because people from all around the world helped to contribute to Viossa's vocabulary.",
|
|
||||||
"image": "flakka.png",
|
|
||||||
"alt": "Flag of the Viossa Language"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Community",
|
|
||||||
"text": "The Viossa community is rich and colourful, drawing from many global traditions due to its worldwide online membership. Since the teaching culture puts an emphasis on linguistic immersion, and discourages prescriptivism, the culture of Viossa is as diverse and varied as the language and the people who speak it. For many, their personal dialect is a key form of identity and expression. The fluid nature of Viossa and lack of defined meanings makes Viossa popular for creative purposes, such as poetry and songwriting.",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"resources": [
|
|
||||||
{
|
|
||||||
"title": "Discord Server",
|
|
||||||
"subtitle": "This is where most of the action happens! Hop on in!",
|
|
||||||
"desc": "Originally started in 2015 something something read the rules here, then click the link below to join!",
|
|
||||||
"link": "https://discord.gg/g3mG2gYjZD",
|
|
||||||
"rulesLink": "https://viossadiskordserver.github.io/rules",
|
|
||||||
"image": "discord.png",
|
|
||||||
"alt": "Discord logo",
|
|
||||||
"joinText": "Join",
|
|
||||||
"rulesText": "Rules"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
export default {
|
|
||||||
"sections": [
|
|
||||||
{
|
|
||||||
"title": "Kafaen afto Viossa",
|
|
||||||
"text": "Viossa tte glossa mahena grun vi nai vil fshtojena na bakadjin, grun vi svinnur ja! De aldjin zovti lera ne",
|
|
||||||
"image": "flakka.png",
|
|
||||||
"alt": "Flag of the Viossa Language"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "History of Viossa",
|
|
||||||
"text": "Viossa began as a Skype group in 2014, created by members of the r/conlangs community on Reddit, as an experiment to simulate the formation of a pidgin language. Pidgins are simplified languages resulting from contact between populations with no shared common language. Unlike most pidgins, which usually have two to three contributor languages, Viossa comes from many diverse languages. This is because people from all around the world helped to contribute to Viossa's vocabulary.",
|
|
||||||
"image": "flakka.png",
|
|
||||||
"alt": "Flag of the Viossa Language"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Community",
|
|
||||||
"text": "The Viossa community is rich and colourful, drawing from many global traditions due to its worldwide online membership. Since the teaching culture puts an emphasis on linguistic immersion, and discourages prescriptivism, the culture of Viossa is as diverse and varied as the language and the people who speak it. For many, their personal dialect is a key form of identity and expression. The fluid nature of Viossa and lack of defined meanings makes Viossa popular for creative purposes, such as poetry and songwriting.",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"resources": [
|
|
||||||
{
|
|
||||||
"title": "Discord Server",
|
|
||||||
"subtitle": "This is where most of the action happens! Hop on in!",
|
|
||||||
"desc": "Originally started in 2015 something something read the rules here, then click the link below to join!",
|
|
||||||
"link": "https://discord.gg/g3mG2gYjZD",
|
|
||||||
"rulesLink": "https://viossadiskordserver.github.io/rules",
|
|
||||||
"image": "discord.png",
|
|
||||||
"alt": "Discord logo",
|
|
||||||
"joinText": "Join",
|
|
||||||
"rulesText": "Rules"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
|
||||||
import type { RouteRecordRaw } from 'vue-router'
|
|
||||||
|
|
||||||
import HomePage from '@/components/pages/HomePage.vue'
|
|
||||||
import ResourcesPage from '@/components/pages/ResourcesPage.vue'
|
|
||||||
|
|
||||||
const routes: RouteRecordRaw[] = [
|
|
||||||
{
|
|
||||||
path: '/',
|
|
||||||
name: 'Home',
|
|
||||||
component: HomePage,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/resources',
|
|
||||||
name: 'Resources',
|
|
||||||
component: ResourcesPage,
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// path: '/:pathMatch(.*)*', // Vue Router 4 catch-all for 404s
|
|
||||||
// name: 'NotFound',
|
|
||||||
// component: NotFoundPage,
|
|
||||||
// },
|
|
||||||
]
|
|
||||||
|
|
||||||
const router = createRouter({
|
|
||||||
history: createWebHistory(),
|
|
||||||
routes,
|
|
||||||
})
|
|
||||||
|
|
||||||
export default router
|
|
||||||