i18n
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import en from './locales/en'
|
||||
import hu from './locales/hu'
|
||||
|
||||
const savedLocale = localStorage.getItem('locale') ?? 'en'
|
||||
|
||||
export const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: savedLocale,
|
||||
fallbackLocale: 'en',
|
||||
messages: { en, hu },
|
||||
})
|
||||
@@ -0,0 +1,157 @@
|
||||
export default {
|
||||
nav: {
|
||||
home: 'Home',
|
||||
catalog: 'Catalog',
|
||||
blog: 'Blog',
|
||||
howtos: 'How-tos',
|
||||
code: 'Code',
|
||||
team: 'Team',
|
||||
contact: 'Contact us',
|
||||
retro: 'Retro Mode',
|
||||
exitRetro: 'Exit Retro Mode',
|
||||
},
|
||||
common: {
|
||||
status: {
|
||||
released: 'released',
|
||||
demo: 'demo',
|
||||
development: 'development',
|
||||
archived: 'archived',
|
||||
},
|
||||
error: 'Error!',
|
||||
loading: 'Loading...',
|
||||
missingApiConfig: 'Missing API Configuration',
|
||||
failedToConnectWiki: 'Failed to connect to Wiki',
|
||||
},
|
||||
home: {
|
||||
welcomeTo: 'Welcome to',
|
||||
subtitle: 'Teletype Games is an independent game development community built on creative freedom, equality, and an open-source mindset. Our goal is to create experimental and full-fledged games with short development cycles.',
|
||||
startsOn: 'Starts on:',
|
||||
upcomingEvents: 'Upcoming Events',
|
||||
featuredGame: 'Featured Game',
|
||||
playInBrowser: '▶ Play in Browser',
|
||||
viewProjectDetails: 'View Project Details',
|
||||
latestFromYoutube: 'Latest from YouTube',
|
||||
visitChannel: 'Visit Channel ↗',
|
||||
newRelease: 'New Release',
|
||||
watchOnYoutube: 'Watch on YouTube',
|
||||
note: 'Our HowTo-s and blog posts are written by AI with human supervision.',
|
||||
catalog: {
|
||||
title: 'Catalog',
|
||||
desc: 'Here you can find our games. Discover our creations for TIC-80 and other platforms, many of which you can try directly in your browser.',
|
||||
btn: 'Browse Games',
|
||||
},
|
||||
wiki: {
|
||||
title: 'Wiki',
|
||||
desc: 'We gather our public interest development knowledge here. Read through technical descriptions and development logs.',
|
||||
btn: 'Knowledge Base',
|
||||
},
|
||||
git: {
|
||||
title: 'Git Repos',
|
||||
desc: 'All our projects are open source. Browse our code, study our solutions, or even participate in the development.',
|
||||
btn: 'Gitea',
|
||||
},
|
||||
youtube: {
|
||||
title: 'YouTube',
|
||||
desc: 'Watch our development vlogs, gameplay videos, and tutorials on our official YouTube channel.',
|
||||
btn: 'Watch on YouTube',
|
||||
},
|
||||
},
|
||||
contact: {
|
||||
title: 'Contact Us',
|
||||
subtitle: "Have questions, feedback, or just want to say hi? We'd love to hear from you!",
|
||||
joinDiscord: 'Join our Discord',
|
||||
emailUs: 'Email Us',
|
||||
emailDesc: 'For business inquiries, support, or detailed feedback, feel free to drop us an email.',
|
||||
community: 'Community',
|
||||
communityDesc: 'Join our primarily Hungarian-speaking community (English speakers are also welcome!)',
|
||||
discord: {
|
||||
desc: 'We have a vibrant Discord server for real-time chat and support.',
|
||||
link: 'Join Discord Server',
|
||||
},
|
||||
youtube: {
|
||||
desc: 'Watch our latest vlogs and development videos on our channel.',
|
||||
link: 'Visit Channel',
|
||||
},
|
||||
irc: {
|
||||
desc: "If Discord is too modern, find us on IRC!",
|
||||
},
|
||||
bbs: {
|
||||
desc: 'Join us for some retro vibes on our BBS!',
|
||||
},
|
||||
},
|
||||
blog: {
|
||||
badge: 'Community Stories',
|
||||
title: 'Developer Blog',
|
||||
subtitle: 'News, updates, and behind-the-scenes stories from the Teletype Games community.',
|
||||
errorTitle: 'Failed to connect to Wiki',
|
||||
noPostsTitle: 'No blog posts found',
|
||||
noPostsDesc: "We haven't published any blog posts yet. Check back soon!",
|
||||
newPost: 'New Post',
|
||||
readMore: 'Read more',
|
||||
},
|
||||
catalog: {
|
||||
title: 'Our Games',
|
||||
subtitle: 'Discover games made for TIC-80 and other platforms, with versions playable directly in your browser!',
|
||||
filter: {
|
||||
all: 'All',
|
||||
released: 'Released',
|
||||
demo: 'Demo',
|
||||
development: 'Development',
|
||||
archived: 'Archived',
|
||||
},
|
||||
author: 'Author:',
|
||||
platform: 'Platform:',
|
||||
play: '▶ Play',
|
||||
moreInfo: 'ℹ More Info',
|
||||
},
|
||||
catalogShow: {
|
||||
back: '← Back to Catalog',
|
||||
projectInfo: 'Project Info',
|
||||
author: 'Author',
|
||||
platform: 'Platform',
|
||||
license: 'License',
|
||||
about: 'About',
|
||||
latestStable: 'Latest Stable',
|
||||
released: 'Released:',
|
||||
playNow: '▶ Play Now',
|
||||
download: '💾 Download',
|
||||
source: '📄 Source',
|
||||
docs: '📖 Docs',
|
||||
allReleases: 'All Releases',
|
||||
version: 'Version',
|
||||
releaseDate: 'Release Date',
|
||||
devVersions: 'Development Versions',
|
||||
notFound: 'Game not found',
|
||||
failedToLoad: 'Failed to load:',
|
||||
loading: 'Loading...',
|
||||
play: '▶ Play',
|
||||
},
|
||||
team: {
|
||||
title: 'Our Team',
|
||||
subtitle: 'Meet the brilliant minds behind Teletype Games.',
|
||||
},
|
||||
howtos: {
|
||||
badge: 'Knowledge Base',
|
||||
title: 'Tech HowTo Center',
|
||||
subtitle: 'The latest documentation, technical guides, and development logs from our knowledge base.',
|
||||
knowledgeBase: 'Knowledge Base',
|
||||
errorTitle: 'Failed to connect to Wiki',
|
||||
noPagesTitle: 'No pages found',
|
||||
noPagesDesc: "It seems like there aren't any public pages available on the wiki at the moment.",
|
||||
noDesc: 'No description provided.',
|
||||
browseWiki: 'Browse Wiki Home',
|
||||
new: 'New',
|
||||
read: 'Read',
|
||||
},
|
||||
code: {
|
||||
title: 'Codebase',
|
||||
subtitle: 'Explore our collection of open-source projects, study our source code, and contribute to our independent game development tools.',
|
||||
openGitea: 'Open Gitea',
|
||||
noCommits: 'No recent commits found or accessible from public repositories.',
|
||||
recentCommits: 'Recent Commits',
|
||||
language: 'Language:',
|
||||
updated: 'Updated:',
|
||||
authoredBy: 'Authored by',
|
||||
on: 'on',
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
export default {
|
||||
nav: {
|
||||
home: 'Főoldal',
|
||||
catalog: 'Katalógus',
|
||||
blog: 'Blog',
|
||||
howtos: 'Hogyan csináld',
|
||||
code: 'Kód',
|
||||
team: 'Csapat',
|
||||
contact: 'Kapcsolat',
|
||||
retro: 'Retró mód',
|
||||
exitRetro: 'Retró mód kikapcsolása',
|
||||
},
|
||||
common: {
|
||||
status: {
|
||||
released: 'kiadott',
|
||||
demo: 'demó',
|
||||
development: 'fejlesztés',
|
||||
archived: 'archivált',
|
||||
},
|
||||
error: 'Hiba!',
|
||||
loading: 'Betöltés...',
|
||||
missingApiConfig: 'Hiányzó API konfiguráció',
|
||||
failedToConnectWiki: 'Nem sikerült csatlakozni a Wikihez',
|
||||
},
|
||||
home: {
|
||||
welcomeTo: 'Üdvözlünk a',
|
||||
subtitle: 'A Teletype Games egy független játékfejlesztő közösség, amelyet a kreatív szabadság, az egyenlőség és a nyílt forráskódú szemlélet vezérel. Célunk rövid fejlesztési ciklusokkal kísérleti és teljes értékű játékokat létrehozni.',
|
||||
startsOn: 'Kezdete:',
|
||||
upcomingEvents: 'Közelgő események',
|
||||
featuredGame: 'Kiemelt játék',
|
||||
playInBrowser: '▶ Játék böngészőben',
|
||||
viewProjectDetails: 'Projekt részletei',
|
||||
latestFromYoutube: 'Legújabb YouTube-ról',
|
||||
visitChannel: 'Csatorna megtekintése ↗',
|
||||
newRelease: 'Új megjelenés',
|
||||
watchOnYoutube: 'Nézd meg YouTube-on',
|
||||
note: 'A HowTo-k és blogbejegyzések mesterséges intelligenciával íródtak, emberi felügyelet mellett.',
|
||||
catalog: {
|
||||
title: 'Katalógus',
|
||||
desc: 'Itt megtalálod a játékainkat. Fedezd fel alkotásainkat TIC-80-ra és más platformokra, amelyek közül sokat közvetlenül a böngésződben is kipróbálhatsz.',
|
||||
btn: 'Játékok böngészése',
|
||||
},
|
||||
wiki: {
|
||||
title: 'Wiki',
|
||||
desc: 'Itt gyűjtjük össze a közérdekű fejlesztési tudásunkat. Olvasd át a technikai leírásokat és fejlesztési naplókat.',
|
||||
btn: 'Tudásbázis',
|
||||
},
|
||||
git: {
|
||||
title: 'Git tárolók',
|
||||
desc: 'Minden projektünk nyílt forráskódú. Böngészd a kódunkat, tanulmányozd a megoldásainkat, vagy akár részt is vehetsz a fejlesztésben.',
|
||||
btn: 'Gitea',
|
||||
},
|
||||
youtube: {
|
||||
title: 'YouTube',
|
||||
desc: 'Nézd meg fejlesztési vlogjainkat, gameplay videóinkat és tutorialainkat a hivatalos YouTube-csatornánkon.',
|
||||
btn: 'Nézd meg YouTube-on',
|
||||
},
|
||||
},
|
||||
contact: {
|
||||
title: 'Kapcsolat',
|
||||
subtitle: 'Kérdéseid vannak, visszajelzésed van, vagy csak szeretnél üdvözölni? Szívesen hallunk felőled!',
|
||||
joinDiscord: 'Csatlakozz a Discordunkhoz',
|
||||
emailUs: 'Írj emailt',
|
||||
emailDesc: 'Üzleti megkeresésekhez, támogatáshoz vagy részletes visszajelzéshez nyugodtan írj nekünk emailt.',
|
||||
community: 'Közösség',
|
||||
communityDesc: 'Csatlakozz elsősorban magyar nyelvű közösségünkhöz (az angolul beszélők is szívesen látottak!)',
|
||||
discord: {
|
||||
desc: 'Élénk Discord szerverünk van valós idejű csevegéshez és támogatáshoz.',
|
||||
link: 'Csatlakozz a Discord szerverhez',
|
||||
},
|
||||
youtube: {
|
||||
desc: 'Nézd meg legújabb vlogjainkat és fejlesztési videóinkat a csatornánkon.',
|
||||
link: 'Csatorna megtekintése',
|
||||
},
|
||||
irc: {
|
||||
desc: 'Ha a Discord túl modern, találj minket az IRC-n!',
|
||||
},
|
||||
bbs: {
|
||||
desc: 'Csatlakozz hozzánk retró élményekért a BBS-ünkön!',
|
||||
},
|
||||
},
|
||||
blog: {
|
||||
badge: 'Közösségi történetek',
|
||||
title: 'Fejlesztői Blog',
|
||||
subtitle: 'Hírek, frissítések és kulisszák mögötti történetek a Teletype Games közösségből.',
|
||||
errorTitle: 'Nem sikerült csatlakozni a Wikihez',
|
||||
noPostsTitle: 'Nem találhatók blogbejegyzések',
|
||||
noPostsDesc: 'Még nem tettünk közzé blogbejegyzéseket. Nézz vissza hamarosan!',
|
||||
newPost: 'Új bejegyzés',
|
||||
readMore: 'Tovább olvasom',
|
||||
},
|
||||
catalog: {
|
||||
title: 'Játékaink',
|
||||
subtitle: 'Fedezd fel a TIC-80-ra és más platformokra készített játékainkat, amelyeknek közvetlenül a böngésződben is kipróbálhatsz verzióit!',
|
||||
filter: {
|
||||
all: 'Összes',
|
||||
released: 'Kiadott',
|
||||
demo: 'Demó',
|
||||
development: 'Fejlesztés alatt',
|
||||
archived: 'Archivált',
|
||||
},
|
||||
author: 'Szerző:',
|
||||
platform: 'Platform:',
|
||||
play: '▶ Játék',
|
||||
moreInfo: 'ℹ Részletek',
|
||||
},
|
||||
catalogShow: {
|
||||
back: '← Vissza a katalógushoz',
|
||||
projectInfo: 'Projekt infó',
|
||||
author: 'Szerző',
|
||||
platform: 'Platform',
|
||||
license: 'Licensz',
|
||||
about: 'Leírás',
|
||||
latestStable: 'Legújabb stabil',
|
||||
released: 'Kiadva:',
|
||||
playNow: '▶ Játék most',
|
||||
download: '💾 Letöltés',
|
||||
source: '📄 Forráskód',
|
||||
docs: '📖 Dokumentáció',
|
||||
allReleases: 'Összes kiadás',
|
||||
version: 'Verzió',
|
||||
releaseDate: 'Kiadás dátuma',
|
||||
devVersions: 'Fejlesztői verziók',
|
||||
notFound: 'A játék nem található',
|
||||
failedToLoad: 'Nem sikerült betölteni:',
|
||||
loading: 'Betöltés...',
|
||||
play: '▶ Játék',
|
||||
},
|
||||
team: {
|
||||
title: 'Csapatunk',
|
||||
subtitle: 'Ismerd meg a Teletype Games mögött álló zseniális elméket.',
|
||||
},
|
||||
howtos: {
|
||||
badge: 'Tudásbázis',
|
||||
title: 'Tech HowTo Központ',
|
||||
subtitle: 'A legfrissebb dokumentáció, technikai útmutatók és fejlesztési naplók a tudásbázisunkból.',
|
||||
knowledgeBase: 'Tudásbázis',
|
||||
errorTitle: 'Nem sikerült csatlakozni a Wikihez',
|
||||
noPagesTitle: 'Nem találhatók oldalak',
|
||||
noPagesDesc: 'Úgy tűnik, jelenleg nincsenek nyilvánosan elérhető oldalak a wikin.',
|
||||
noDesc: 'Nincs megadva leírás.',
|
||||
browseWiki: 'Wiki főoldal böngészése',
|
||||
new: 'Új',
|
||||
read: 'Olvasás',
|
||||
},
|
||||
code: {
|
||||
title: 'Kódbázis',
|
||||
subtitle: 'Fedezd fel nyílt forráskódú projektek gyűjteményét, tanulmányozd forráskódunkat, és járulj hozzá független játékfejlesztő eszközeinkhez.',
|
||||
openGitea: 'Gitea megnyitása',
|
||||
noCommits: 'Nem találhatók közelmúltbeli commitok a nyilvános tárolókban.',
|
||||
recentCommits: 'Legutóbbi commitok',
|
||||
language: 'Nyelv:',
|
||||
updated: 'Frissítve:',
|
||||
authoredBy: 'Közreműködő:',
|
||||
on: '·',
|
||||
},
|
||||
}
|
||||
@@ -4,14 +4,20 @@
|
||||
<RouterLink to="/" class="text-xl font-bold">Teletype Games</RouterLink>
|
||||
|
||||
<!-- Desktop Navigation -->
|
||||
<nav class="hidden md:flex space-x-4">
|
||||
<RouterLink to="/" class="p-2 hover:text-purple-300 transition-colors duration-200">Home</RouterLink>
|
||||
<RouterLink to="/catalog" class="p-2 hover:text-purple-300 transition-colors duration-200">Catalog</RouterLink>
|
||||
<RouterLink to="/blog" class="p-2 hover:text-purple-300 transition-colors duration-200">Blog</RouterLink>
|
||||
<RouterLink to="/howtos" class="p-2 hover:text-purple-300 transition-colors duration-200">How-tos</RouterLink>
|
||||
<RouterLink to="/code" class="p-2 hover:text-purple-300 transition-colors duration-200">Code</RouterLink>
|
||||
<RouterLink to="/team" class="p-2 hover:text-purple-300 transition-colors duration-200">Team</RouterLink>
|
||||
<RouterLink to="/contact" class="p-2 hover:text-purple-300 transition-colors duration-200">Contact us</RouterLink>
|
||||
<nav class="hidden md:flex items-center space-x-4">
|
||||
<RouterLink to="/" class="p-2 hover:text-purple-300 transition-colors duration-200">{{ t('nav.home') }}</RouterLink>
|
||||
<RouterLink to="/catalog" class="p-2 hover:text-purple-300 transition-colors duration-200">{{ t('nav.catalog') }}</RouterLink>
|
||||
<RouterLink to="/blog" class="p-2 hover:text-purple-300 transition-colors duration-200">{{ t('nav.blog') }}</RouterLink>
|
||||
<RouterLink to="/howtos" class="p-2 hover:text-purple-300 transition-colors duration-200">{{ t('nav.howtos') }}</RouterLink>
|
||||
<RouterLink to="/code" class="p-2 hover:text-purple-300 transition-colors duration-200">{{ t('nav.code') }}</RouterLink>
|
||||
<RouterLink to="/team" class="p-2 hover:text-purple-300 transition-colors duration-200">{{ t('nav.team') }}</RouterLink>
|
||||
<RouterLink to="/contact" class="p-2 hover:text-purple-300 transition-colors duration-200">{{ t('nav.contact') }}</RouterLink>
|
||||
|
||||
<div class="flex items-center gap-1 text-sm font-bold ml-2 border-l border-gray-600 pl-4">
|
||||
<button @click="switchLocale('en')" :class="locale === 'en' ? 'text-white' : 'text-gray-400 hover:text-white'" class="transition-colors px-1">EN</button>
|
||||
<span class="text-gray-600">|</span>
|
||||
<button @click="switchLocale('hu')" :class="locale === 'hu' ? 'text-white' : 'text-gray-400 hover:text-white'" class="transition-colors px-1">HU</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Hamburger Button (Mobile only) -->
|
||||
@@ -23,13 +29,18 @@
|
||||
|
||||
<!-- Mobile Navigation -->
|
||||
<nav v-show="menuOpen" class="md:hidden absolute top-full left-0 w-full bg-gray-800 flex flex-col items-center py-4 space-y-2 z-50">
|
||||
<RouterLink to="/" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">Home</RouterLink>
|
||||
<RouterLink to="/catalog" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">Catalog</RouterLink>
|
||||
<RouterLink to="/blog" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">Blog</RouterLink>
|
||||
<RouterLink to="/howtos" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">How-tos</RouterLink>
|
||||
<RouterLink to="/code" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">Code</RouterLink>
|
||||
<RouterLink to="/team" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">Team</RouterLink>
|
||||
<RouterLink to="/contact" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">Contact us</RouterLink>
|
||||
<RouterLink to="/" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">{{ t('nav.home') }}</RouterLink>
|
||||
<RouterLink to="/catalog" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">{{ t('nav.catalog') }}</RouterLink>
|
||||
<RouterLink to="/blog" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">{{ t('nav.blog') }}</RouterLink>
|
||||
<RouterLink to="/howtos" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">{{ t('nav.howtos') }}</RouterLink>
|
||||
<RouterLink to="/code" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">{{ t('nav.code') }}</RouterLink>
|
||||
<RouterLink to="/team" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">{{ t('nav.team') }}</RouterLink>
|
||||
<RouterLink to="/contact" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">{{ t('nav.contact') }}</RouterLink>
|
||||
<div class="flex items-center gap-2 pt-2 border-t border-gray-700 w-full justify-center text-sm font-bold">
|
||||
<button @click="switchLocale('en')" :class="locale === 'en' ? 'text-white' : 'text-gray-400'" class="transition-colors px-2 py-1">EN</button>
|
||||
<span class="text-gray-600">|</span>
|
||||
<button @click="switchLocale('hu')" :class="locale === 'hu' ? 'text-white' : 'text-gray-400'" class="transition-colors px-2 py-1">HU</button>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
@@ -39,7 +50,7 @@
|
||||
|
||||
<div class="retro-toggle-bar">
|
||||
<button class="retro-toggle-btn" @click="toggleRetroMode">
|
||||
🖥 {{ isRetroMode ? 'Exit Retro Mode' : 'Retro Mode' }}
|
||||
🖥 {{ isRetroMode ? t('nav.exitRetro') : t('nav.retro') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -49,8 +60,11 @@
|
||||
import { watch } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { RouterLink, useRoute } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useUiStore } from '../stores/ui.store'
|
||||
|
||||
const { t, locale } = useI18n()
|
||||
|
||||
const ui = useUiStore()
|
||||
const { isRetroMode, menuOpen } = storeToRefs(ui)
|
||||
const { toggleMenu, toggleRetroMode } = ui
|
||||
@@ -59,6 +73,11 @@ const route = useRoute()
|
||||
watch(() => route.path, () => {
|
||||
ui.closeMenu()
|
||||
})
|
||||
|
||||
function switchLocale(lang: string) {
|
||||
locale.value = lang
|
||||
localStorage.setItem('locale', lang)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import { router } from './router/index.router'
|
||||
import { i18n } from './i18n'
|
||||
import App from './App.vue'
|
||||
import './styles/global.css'
|
||||
import './styles/retro.css'
|
||||
|
||||
createApp(App).use(createPinia()).use(router).mount('#app')
|
||||
createApp(App).use(createPinia()).use(router).use(i18n).mount('#app')
|
||||
|
||||
@@ -7,13 +7,11 @@
|
||||
</div>
|
||||
|
||||
<div class="hero-container">
|
||||
<div class="hero-badge">Community Stories</div>
|
||||
<div class="hero-badge">{{ t('blog.badge') }}</div>
|
||||
<h1 class="hero-title">
|
||||
Developer <span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-400">Blog</span>
|
||||
</h1>
|
||||
<p class="hero-subtitle mb-10">
|
||||
News, updates, and behind-the-scenes stories from the Teletype Games community.
|
||||
</p>
|
||||
<p class="hero-subtitle mb-10">{{ t('blog.subtitle') }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -21,15 +19,15 @@
|
||||
<div v-if="error" class="error-banner" role="alert">
|
||||
<span class="text-2xl">⚠️</span>
|
||||
<div>
|
||||
<h3 class="error-banner-title">Failed to connect to Wiki</h3>
|
||||
<h3 class="error-banner-title">{{ t('blog.errorTitle') }}</h3>
|
||||
<p class="error-banner-desc">{{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="!loading && blogPages.length === 0" class="empty-state">
|
||||
<div class="empty-state-icon">📭</div>
|
||||
<h2 class="empty-state-title">No blog posts found</h2>
|
||||
<p class="empty-state-desc">We haven't published any blog posts yet. Check back soon!</p>
|
||||
<h2 class="empty-state-title">{{ t('blog.noPostsTitle') }}</h2>
|
||||
<p class="empty-state-desc">{{ t('blog.noPostsDesc') }}</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="blog-posts-list">
|
||||
@@ -40,7 +38,7 @@
|
||||
<div class="blog-post-timestamp">
|
||||
<span v-if="isNew(page.createdAt)" class="new-post-badge">
|
||||
<span class="new-post-dot"></span>
|
||||
New Post
|
||||
{{ t('blog.newPost') }}
|
||||
</span>
|
||||
<span>{{ formatDateTime(page.createdAt) }}</span>
|
||||
</div>
|
||||
@@ -60,7 +58,7 @@
|
||||
|
||||
<div class="mt-6">
|
||||
<RouterLink :to="getPermalink(page.path)" class="read-more-btn">
|
||||
Read more
|
||||
{{ t('blog.readMore') }}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-1" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
@@ -77,9 +75,12 @@
|
||||
import { onMounted } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { formatDateTime } from '../../lib/dateFormat'
|
||||
import { useBlogStore } from '../../stores/blog.store'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const store = useBlogStore()
|
||||
const { pages: blogPages, loading, error } = storeToRefs(store)
|
||||
const { isNew, getPermalink, getCleanPreview } = store
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<header class="hero-section-gradient from-purple-600 to-indigo-600 py-16">
|
||||
<div class="hero-container">
|
||||
<h1 class="hero-title">Our Games</h1>
|
||||
<p class="hero-subtitle text-purple-50">Discover games made for TIC-80 and other platforms, with versions playable directly in your browser!</p>
|
||||
<h1 class="hero-title">{{ t('catalog.title') }}</h1>
|
||||
<p class="hero-subtitle text-purple-50">{{ t('catalog.subtitle') }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
:class="['filter-btn', { active: activeFilter === f }]"
|
||||
@click="activeFilter = f"
|
||||
>
|
||||
{{ f.charAt(0).toUpperCase() + f.slice(1) }}
|
||||
{{ t(`catalog.filter.${f}`) }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
<RouterLink :to="`/catalog/${software.name}`" class="hover:text-purple-600 transition-colors">
|
||||
<h2 class="software-title mb-0">{{ software.title }}</h2>
|
||||
</RouterLink>
|
||||
<span :class="`status-badge status-${software.status}`">{{ software.status }}</span>
|
||||
<span :class="`status-badge status-${software.status}`">{{ t(`common.status.${software.status}`) }}</span>
|
||||
</div>
|
||||
<p class="software-desc max-w-2xl">{{ software.desc }}</p>
|
||||
<div class="software-meta">
|
||||
<span>Author: <span class="text-gray-900 font-medium">{{ software.author }}</span></span>
|
||||
<span>{{ t('catalog.author') }} <span class="text-gray-900 font-medium">{{ software.author }}</span></span>
|
||||
<span class="mx-2 text-gray-300">•</span>
|
||||
<span>Platform: <span class="text-gray-900 font-medium">{{ software.platform }}</span></span>
|
||||
<span>{{ t('catalog.platform') }} <span class="text-gray-900 font-medium">{{ software.platform }}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -47,9 +47,9 @@
|
||||
:href="getLatestStable(releases).htmlFolderPath"
|
||||
target="_blank"
|
||||
class="btn-play-sm"
|
||||
>▶ Play</a>
|
||||
>{{ t('catalog.play') }}</a>
|
||||
<RouterLink :to="`/catalog/${software.name}`" class="btn-info-sm">
|
||||
ℹ More Info
|
||||
{{ t('catalog.moreInfo') }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,8 +64,11 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useSoftwareStore } from '../../stores/software.store'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const filters = ['all', 'released', 'demo', 'development', 'archived']
|
||||
const activeFilter = ref('released')
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
<div class="hero-container">
|
||||
<nav class="mb-8">
|
||||
<RouterLink to="/catalog" class="text-purple-200 hover:text-white transition-colors flex items-center gap-2 font-medium">
|
||||
← Back to Catalog
|
||||
{{ t('catalogShow.back') }}
|
||||
</RouterLink>
|
||||
</nav>
|
||||
|
||||
<div v-if="software" class="flex flex-col md:flex-row md:items-end justify-between gap-6">
|
||||
<div class="flex-grow">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<span :class="`status-badge status-${software.status} px-3 py-1`">{{ software.status }}</span>
|
||||
<span :class="`status-badge status-${software.status} px-3 py-1`">{{ t(`common.status.${software.status}`) }}</span>
|
||||
<span class="text-purple-300 font-mono text-sm tracking-widest uppercase">{{ software.platform }}</span>
|
||||
</div>
|
||||
<h1 class="text-4xl md:text-6xl font-black text-white mb-4 leading-tight">{{ software.title }}</h1>
|
||||
@@ -31,19 +31,19 @@
|
||||
<img :src="software.imageUrl" :alt="software.title" class="max-h-48 w-auto object-contain border-4 border-gray-100 shadow-sm" />
|
||||
</div>
|
||||
<h2 class="text-xl font-bold text-gray-900 mb-6 flex items-center gap-2">
|
||||
<span class="text-purple-600">ℹ</span> Project Info
|
||||
<span class="text-purple-600">ℹ</span> {{ t('catalogShow.projectInfo') }}
|
||||
</h2>
|
||||
<dl class="space-y-4">
|
||||
<div>
|
||||
<dt class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-1">Author</dt>
|
||||
<dt class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-1">{{ t('catalogShow.author') }}</dt>
|
||||
<dd class="text-gray-900 font-medium">{{ software.author }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-1">Platform</dt>
|
||||
<dt class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-1">{{ t('catalogShow.platform') }}</dt>
|
||||
<dd class="text-gray-900 font-medium">{{ software.platform }}</dd>
|
||||
</div>
|
||||
<div v-if="software.license">
|
||||
<dt class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-1">License</dt>
|
||||
<dt class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-1">{{ t('catalogShow.license') }}</dt>
|
||||
<dd class="text-gray-900 font-medium">{{ software.license }}</dd>
|
||||
</div>
|
||||
<div v-for="link in software.externalLinks" :key="link.url">
|
||||
@@ -61,7 +61,7 @@
|
||||
<!-- Main Content Area -->
|
||||
<div class="lg:col-span-2 space-y-8">
|
||||
<div v-if="software.story" class="bg-white rounded-3xl shadow-xl p-8 border border-gray-100">
|
||||
<h2 class="text-xl font-bold text-gray-900 mb-4">About</h2>
|
||||
<h2 class="text-xl font-bold text-gray-900 mb-4">{{ t('catalogShow.about') }}</h2>
|
||||
<p class="text-gray-700 leading-relaxed whitespace-pre-line">{{ software.story }}</p>
|
||||
</div>
|
||||
|
||||
@@ -69,24 +69,24 @@
|
||||
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-6">
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="px-2 py-0.5 bg-white/20 text-white text-[10px] font-black uppercase rounded tracking-widest">Latest Stable</span>
|
||||
<span class="px-2 py-0.5 bg-white/20 text-white text-[10px] font-black uppercase rounded tracking-widest">{{ t('catalogShow.latestStable') }}</span>
|
||||
</div>
|
||||
<h2 class="text-4xl font-black mb-1">{{ latestStable.version }}</h2>
|
||||
<p class="text-indigo-100 text-sm">Released: {{ formatDateTime(latestStable.UpdatedAt) }}</p>
|
||||
<p class="text-indigo-100 text-sm">{{ t('catalogShow.released') }} {{ formatDateTime(latestStable.UpdatedAt) }}</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 sm:grid-cols-4 md:grid-cols-2 xl:grid-cols-4 gap-2 w-full md:w-auto">
|
||||
<a v-if="latestStable.htmlFolderPath" :href="latestStable.htmlFolderPath" target="_blank" class="flex items-center justify-center py-3 px-4 bg-white text-indigo-900 font-bold rounded-xl transition-all hover:bg-indigo-50 shadow-lg shadow-black/10 text-sm whitespace-nowrap">▶ Play Now</a>
|
||||
<a v-if="latestStable.cartridgePath" :href="latestStable.cartridgePath" target="_blank" class="flex items-center justify-center py-3 px-4 bg-indigo-500/30 border border-indigo-400/30 text-white font-bold rounded-xl transition-all hover:bg-indigo-500/40 text-sm whitespace-nowrap">💾 Download</a>
|
||||
<a v-if="latestStable.sourcePath" :href="latestStable.sourcePath" target="_blank" class="flex items-center justify-center py-3 px-4 bg-indigo-500/30 border border-indigo-400/30 text-white font-bold rounded-xl transition-all hover:bg-indigo-500/40 text-sm whitespace-nowrap">📄 Source</a>
|
||||
<a v-if="latestStable.docsFolderPath" :href="latestStable.docsFolderPath" target="_blank" class="flex items-center justify-center py-3 px-4 bg-indigo-500/30 border border-indigo-400/30 text-white font-bold rounded-xl transition-all hover:bg-indigo-500/40 text-sm whitespace-nowrap">📖 Docs</a>
|
||||
<a v-if="latestStable.htmlFolderPath" :href="latestStable.htmlFolderPath" target="_blank" class="flex items-center justify-center py-3 px-4 bg-white text-indigo-900 font-bold rounded-xl transition-all hover:bg-indigo-50 shadow-lg shadow-black/10 text-sm whitespace-nowrap">{{ t('catalogShow.playNow') }}</a>
|
||||
<a v-if="latestStable.cartridgePath" :href="latestStable.cartridgePath" target="_blank" class="flex items-center justify-center py-3 px-4 bg-indigo-500/30 border border-indigo-400/30 text-white font-bold rounded-xl transition-all hover:bg-indigo-500/40 text-sm whitespace-nowrap">{{ t('catalogShow.download') }}</a>
|
||||
<a v-if="latestStable.sourcePath" :href="latestStable.sourcePath" target="_blank" class="flex items-center justify-center py-3 px-4 bg-indigo-500/30 border border-indigo-400/30 text-white font-bold rounded-xl transition-all hover:bg-indigo-500/40 text-sm whitespace-nowrap">{{ t('catalogShow.source') }}</a>
|
||||
<a v-if="latestStable.docsFolderPath" :href="latestStable.docsFolderPath" target="_blank" class="flex items-center justify-center py-3 px-4 bg-indigo-500/30 border border-indigo-400/30 text-white font-bold rounded-xl transition-all hover:bg-indigo-500/40 text-sm whitespace-nowrap">{{ t('catalogShow.docs') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-3xl shadow-xl overflow-hidden border border-gray-100">
|
||||
<div class="p-8 border-b border-gray-100">
|
||||
<h2 class="text-2xl font-bold text-gray-900">All Releases</h2>
|
||||
<h2 class="text-2xl font-bold text-gray-900">{{ t('catalogShow.allReleases') }}</h2>
|
||||
</div>
|
||||
<div class="p-0">
|
||||
<!-- Desktop Table -->
|
||||
@@ -94,8 +94,8 @@
|
||||
<table class="w-full text-left">
|
||||
<thead class="bg-gray-50 text-gray-500 text-xs font-bold uppercase tracking-widest">
|
||||
<tr>
|
||||
<th class="px-8 py-4">Version</th>
|
||||
<th class="px-8 py-4">Release Date</th>
|
||||
<th class="px-8 py-4">{{ t('catalogShow.version') }}</th>
|
||||
<th class="px-8 py-4">{{ t('catalogShow.releaseDate') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
@@ -103,25 +103,25 @@
|
||||
<td class="px-8 py-4">
|
||||
<div class="font-bold text-gray-900 text-lg mb-2">{{ release.version }}</div>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<a v-if="release.htmlFolderPath" :href="release.htmlFolderPath" target="_blank" class="text-purple-600 hover:text-purple-900 font-bold text-sm flex items-center gap-1">▶ Play</a>
|
||||
<a v-if="release.cartridgePath" :href="release.cartridgePath" target="_blank" class="text-blue-600 hover:text-blue-900 font-bold text-sm flex items-center gap-1">💾 Download</a>
|
||||
<a v-if="release.sourcePath" :href="release.sourcePath" target="_blank" class="text-green-600 hover:text-green-900 font-bold text-sm flex items-center gap-1">📄 Source</a>
|
||||
<a v-if="release.docsFolderPath" :href="release.docsFolderPath" target="_blank" class="text-yellow-600 hover:text-yellow-900 font-bold text-sm flex items-center gap-1">📖 Docs</a>
|
||||
<a v-if="release.htmlFolderPath" :href="release.htmlFolderPath" target="_blank" class="text-purple-600 hover:text-purple-900 font-bold text-sm flex items-center gap-1">{{ t('catalogShow.play') }}</a>
|
||||
<a v-if="release.cartridgePath" :href="release.cartridgePath" target="_blank" class="text-blue-600 hover:text-blue-900 font-bold text-sm flex items-center gap-1">{{ t('catalogShow.download') }}</a>
|
||||
<a v-if="release.sourcePath" :href="release.sourcePath" target="_blank" class="text-green-600 hover:text-green-900 font-bold text-sm flex items-center gap-1">{{ t('catalogShow.source') }}</a>
|
||||
<a v-if="release.docsFolderPath" :href="release.docsFolderPath" target="_blank" class="text-yellow-600 hover:text-yellow-900 font-bold text-sm flex items-center gap-1">{{ t('catalogShow.docs') }}</a>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-8 py-4 text-gray-500 align-top pt-5">{{ formatDateTime(release.UpdatedAt) }}</td>
|
||||
</tr>
|
||||
|
||||
<tr v-if="devReleases.length > 0" class="bg-yellow-50/30">
|
||||
<td colspan="2" class="px-8 py-3 text-[10px] font-black text-yellow-700 uppercase tracking-tighter">Development Versions</td>
|
||||
<td colspan="2" class="px-8 py-3 text-[10px] font-black text-yellow-700 uppercase tracking-tighter">{{ t('catalogShow.devVersions') }}</td>
|
||||
</tr>
|
||||
|
||||
<tr v-for="release in devReleases" :key="release.version" class="bg-yellow-50/10 hover:bg-yellow-50/30 transition-colors">
|
||||
<td class="px-8 py-4">
|
||||
<div class="font-bold text-yellow-800 text-lg mb-2">{{ release.version }}</div>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<a v-if="release.htmlFolderPath" :href="release.htmlFolderPath" target="_blank" class="text-purple-600 hover:text-purple-900 font-bold text-sm flex items-center gap-1">▶ Play</a>
|
||||
<a v-if="release.cartridgePath" :href="release.cartridgePath" target="_blank" class="text-blue-600 hover:text-blue-900 font-bold text-sm flex items-center gap-1">💾 Download</a>
|
||||
<a v-if="release.htmlFolderPath" :href="release.htmlFolderPath" target="_blank" class="text-purple-600 hover:text-purple-900 font-bold text-sm flex items-center gap-1">{{ t('catalogShow.play') }}</a>
|
||||
<a v-if="release.cartridgePath" :href="release.cartridgePath" target="_blank" class="text-blue-600 hover:text-blue-900 font-bold text-sm flex items-center gap-1">{{ t('catalogShow.download') }}</a>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-8 py-4 text-gray-500 align-top pt-5">{{ formatDateTime(release.UpdatedAt) }}</td>
|
||||
@@ -145,10 +145,10 @@
|
||||
<span v-if="release.version.startsWith('dev-')" class="px-2 py-0.5 bg-yellow-100 text-yellow-800 text-[10px] font-black uppercase rounded">Dev</span>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<a v-if="release.htmlFolderPath" :href="release.htmlFolderPath" target="_blank" class="flex items-center justify-center py-2 bg-purple-100 text-purple-700 font-bold rounded-lg text-sm">Play</a>
|
||||
<a v-if="release.cartridgePath" :href="release.cartridgePath" target="_blank" class="flex items-center justify-center py-2 bg-blue-100 text-blue-700 font-bold rounded-lg text-sm">Download</a>
|
||||
<a v-if="release.sourcePath" :href="release.sourcePath" target="_blank" class="flex items-center justify-center py-2 bg-green-100 text-green-700 font-bold rounded-lg text-sm">Source</a>
|
||||
<a v-if="release.docsFolderPath" :href="release.docsFolderPath" target="_blank" class="flex items-center justify-center py-2 bg-yellow-100 text-yellow-700 font-bold rounded-lg text-sm">Docs</a>
|
||||
<a v-if="release.htmlFolderPath" :href="release.htmlFolderPath" target="_blank" class="flex items-center justify-center py-2 bg-purple-100 text-purple-700 font-bold rounded-lg text-sm">{{ t('catalogShow.play') }}</a>
|
||||
<a v-if="release.cartridgePath" :href="release.cartridgePath" target="_blank" class="flex items-center justify-center py-2 bg-blue-100 text-blue-700 font-bold rounded-lg text-sm">{{ t('catalogShow.download') }}</a>
|
||||
<a v-if="release.sourcePath" :href="release.sourcePath" target="_blank" class="flex items-center justify-center py-2 bg-green-100 text-green-700 font-bold rounded-lg text-sm">{{ t('catalogShow.source') }}</a>
|
||||
<a v-if="release.docsFolderPath" :href="release.docsFolderPath" target="_blank" class="flex items-center justify-center py-2 bg-yellow-100 text-yellow-700 font-bold rounded-lg text-sm">{{ t('catalogShow.docs') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -160,7 +160,7 @@
|
||||
|
||||
<main v-else class="main-container -mt-10">
|
||||
<div class="bg-white rounded-3xl shadow-xl p-12 text-center text-gray-400">
|
||||
{{ error || 'Loading...' }}
|
||||
{{ error || t('catalogShow.loading') }}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
@@ -169,10 +169,12 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { RouterLink, useRoute } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { formatDateTime } from '../../lib/dateFormat'
|
||||
import { useSoftwareStore } from '../../stores/software.store'
|
||||
import type { Release, Software } from '../../lib/interfaces/software.interface'
|
||||
|
||||
const { t } = useI18n()
|
||||
const route = useRoute()
|
||||
const store = useSoftwareStore()
|
||||
|
||||
@@ -203,10 +205,10 @@ onMounted(async () => {
|
||||
software.value = item.software
|
||||
releases.value = item.releases
|
||||
} else {
|
||||
error.value = 'Game not found'
|
||||
error.value = t('catalogShow.notFound')
|
||||
}
|
||||
} catch (e: any) {
|
||||
error.value = `Failed to load: ${e.message}`
|
||||
error.value = `${t('catalogShow.failedToLoad')} ${e.message}`
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
<template>
|
||||
<header class="hero-section-gradient from-teal-600 to-green-600 py-20">
|
||||
<div class="hero-container max-w-4xl">
|
||||
<h1 class="hero-title">Codebase</h1>
|
||||
<p class="hero-subtitle text-teal-50 mb-10">
|
||||
Explore our collection of open-source projects, study our source code, and contribute to our independent game development tools.
|
||||
</p>
|
||||
<h1 class="hero-title">{{ t('code.title') }}</h1>
|
||||
<p class="hero-subtitle text-teal-50 mb-10">{{ t('code.subtitle') }}</p>
|
||||
<a href="https://git.teletype.hu" target="_blank" class="btn-hero-teal">
|
||||
Open Gitea
|
||||
{{ t('code.openGitea') }}
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="main-container">
|
||||
<div v-if="error" class="error-alert" role="alert">
|
||||
<strong class="font-bold">Error!</strong>
|
||||
<strong class="font-bold">{{ t('common.error') }}</strong>
|
||||
<span class="block sm:inline"> {{ error }}</span>
|
||||
</div>
|
||||
|
||||
@@ -25,15 +23,15 @@
|
||||
</a>
|
||||
</h3>
|
||||
<p v-if="repo.description" class="repo-card-desc">{{ repo.description }}</p>
|
||||
<p v-if="repo.language" class="repo-card-meta">Language: {{ repo.language }}</p>
|
||||
<p class="repo-card-meta">Updated: {{ formatDateTime(repo.updated_at) }}</p>
|
||||
<p v-if="repo.language" class="repo-card-meta">{{ t('code.language') }} {{ repo.language }}</p>
|
||||
<p class="repo-card-meta">{{ t('code.updated') }} {{ formatDateTime(repo.updated_at) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="commits-section-title">Recent Commits</h2>
|
||||
<h2 class="commits-section-title">{{ t('code.recentCommits') }}</h2>
|
||||
|
||||
<p v-if="!error && recentCommits.length === 0" class="empty-commits-msg">
|
||||
No recent commits found or accessible from public repositories.
|
||||
{{ t('code.noCommits') }}
|
||||
</p>
|
||||
|
||||
<div class="commits-list">
|
||||
@@ -47,7 +45,7 @@
|
||||
: <span class="text-gray-700">{{ commit.message.split('\n')[0] }}</span>
|
||||
</p>
|
||||
<p class="commit-meta">
|
||||
Authored by <span class="font-bold">{{ commit.author.name }}</span> on {{ formatDateTime(commit.date) }}
|
||||
{{ t('code.authoredBy') }} <span class="font-bold">{{ commit.author.name }}</span> {{ t('code.on') }} {{ formatDateTime(commit.date) }}
|
||||
<a :href="commit.url" target="_blank" class="commit-sha-link">
|
||||
<span class="font-mono text-xs">{{ commit.sha.substring(0, 7) }}</span>
|
||||
</a>
|
||||
@@ -61,9 +59,12 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { formatDateTime } from '../../lib/dateFormat'
|
||||
import { useGitStore } from '../../stores/git.store'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const store = useGitStore()
|
||||
const { repos: publicRepos, commits: recentCommits, error } = storeToRefs(store)
|
||||
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<template>
|
||||
<header class="hero-section-gradient from-blue-600 to-indigo-700 py-20 text-white">
|
||||
<div class="hero-container text-center">
|
||||
<h1 class="hero-title mb-6">Contact Us</h1>
|
||||
<p class="hero-subtitle mb-10 text-blue-100">
|
||||
Have questions, feedback, or just want to say hi? We'd love to hear from you!
|
||||
</p>
|
||||
<h1 class="hero-title mb-6">{{ t('contact.title') }}</h1>
|
||||
<p class="hero-subtitle mb-10 text-blue-100">{{ t('contact.subtitle') }}</p>
|
||||
<a :href="DISCORD_INVITE_LINK" target="_blank" class="discord-hero-btn">
|
||||
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037 19.736 19.736 0 0 0-4.885 1.515.069.069 0 0 0-.032.027C.533 9.048-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.862-1.297 1.197-1.99.051-.105.001-.23-.106-.272a13.223 13.223 0 0 1-1.878-.894.077.077 0 0 1-.007-.128c.126-.094.252-.192.372-.29a.074.074 0 0 1 .077-.01c3.927 1.793 8.18 1.793 12.061 0a.074.074 0 0 1 .077.01c.12.098.246.196.373.29a.077.077 0 0 1-.006.128 12.299 12.299 0 0 1-1.878.894.077.077 0 0 0-.106.272c.335.693.735 1.36 1.197 1.99a.078.078 0 0 0 .084.028 19.83 19.83 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.182 0-2.156-1.085-2.156-2.419 0-1.333.956-2.419 2.156-2.419 1.21 0 2.176 1.096 2.156 2.419 0 1.334-.956 2.419-2.156 2.419zm7.974 0c-1.182 0-2.156-1.085-2.156-2.419 0-1.333.955-2.419 2.156-2.419 1.21 0 2.176 1.096 2.156 2.419 0 1.334-.946 2.419-2.156 2.419z"/>
|
||||
</svg>
|
||||
Join our Discord
|
||||
{{ t('contact.joinDiscord') }}
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
@@ -18,11 +16,9 @@
|
||||
<div class="contact-grid">
|
||||
<div class="contact-card">
|
||||
<h2 class="contact-card-title">
|
||||
<span class="text-3xl">📧</span> Email Us
|
||||
<span class="text-3xl">📧</span> {{ t('contact.emailUs') }}
|
||||
</h2>
|
||||
<p class="contact-card-desc">
|
||||
For business inquiries, support, or detailed feedback, feel free to drop us an email.
|
||||
</p>
|
||||
<p class="contact-card-desc">{{ t('contact.emailDesc') }}</p>
|
||||
<div @click="openEmail" class="email-link cursor-pointer">
|
||||
contact@teletype.hu
|
||||
</div>
|
||||
@@ -30,32 +26,30 @@
|
||||
|
||||
<div class="contact-card">
|
||||
<h2 class="contact-card-title">
|
||||
<span class="text-3xl">💬</span> Community
|
||||
<span class="text-3xl">💬</span> {{ t('contact.community') }}
|
||||
</h2>
|
||||
<p class="contact-card-desc mb-8">
|
||||
Join our primarily Hungarian-speaking community (English speakers are also welcome!).
|
||||
</p>
|
||||
<p class="contact-card-desc mb-8">{{ t('contact.communityDesc') }}</p>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 justify-center">
|
||||
<div class="community-section border-[#5865F2]">
|
||||
<h3 class="community-section-title text-[#5865F2]">Discord</h3>
|
||||
<p class="community-section-desc">We have a vibrant Discord server for real-time chat and support.</p>
|
||||
<p class="community-section-desc">{{ t('contact.discord.desc') }}</p>
|
||||
<a :href="DISCORD_INVITE_LINK" target="_blank" class="community-link-discord">
|
||||
Join Discord Server <span>→</span>
|
||||
{{ t('contact.discord.link') }} <span>→</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="community-section border-red-600">
|
||||
<h3 class="community-section-title text-red-600">YouTube</h3>
|
||||
<p class="community-section-desc">Watch our latest vlogs and development videos on our channel.</p>
|
||||
<p class="community-section-desc">{{ t('contact.youtube.desc') }}</p>
|
||||
<a href="https://www.youtube.com/@teletypegames" target="_blank" class="community-link-youtube">
|
||||
Visit Channel <span>→</span>
|
||||
{{ t('contact.youtube.link') }} <span>→</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="community-section border-green-500">
|
||||
<h3 class="community-section-title text-green-700">IRC</h3>
|
||||
<p class="text-sm text-gray-600 mb-3">If Discord is too modern, find us on IRC!</p>
|
||||
<p class="text-sm text-gray-600 mb-3">{{ t('contact.irc.desc') }}</p>
|
||||
<div class="irc-box">
|
||||
<span class="irc-network">Network: Libera.Chat</span>
|
||||
<code class="irc-channel">#teletypegames</code>
|
||||
@@ -64,7 +58,7 @@
|
||||
|
||||
<div class="community-section border-amber-500">
|
||||
<h3 class="community-section-title text-amber-700">BBS</h3>
|
||||
<p class="community-section-desc">Join us for some retro vibes on our BBS!</p>
|
||||
<p class="community-section-desc">{{ t('contact.bbs.desc') }}</p>
|
||||
<div class="bbs-box">
|
||||
<span class="bbs-host">Host: games.teletype.hu</span>
|
||||
<code class="bbs-port">Port: 2323</code>
|
||||
@@ -77,6 +71,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const DISCORD_INVITE_LINK = import.meta.env.DISCORD_INVITE_LINK || 'https://discord.gg/your-discord-link'
|
||||
|
||||
function openEmail() {
|
||||
|
||||
@@ -8,13 +8,11 @@
|
||||
</div>
|
||||
|
||||
<div class="hero-container">
|
||||
<div class="hero-badge">Welcome to</div>
|
||||
<div class="hero-badge">{{ t('home.welcomeTo') }}</div>
|
||||
<h1 class="hero-title">
|
||||
Teletype <span class="text-transparent bg-clip-text bg-gradient-to-r from-violet-400 to-fuchsia-400">Games</span>
|
||||
</h1>
|
||||
<p class="hero-subtitle">
|
||||
Teletype Games is an independent game development community built on creative freedom, equality, and an open-source mindset. Our goal is to create experimental and full-fledged games with short development cycles.
|
||||
</p>
|
||||
<p class="hero-subtitle">{{ t('home.subtitle') }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -24,10 +22,10 @@
|
||||
<div class="countdown-card">
|
||||
<h2 class="countdown-event-name">{{ nextEvent.name }}</h2>
|
||||
<div class="countdown-timer">{{ countdownText }}</div>
|
||||
<p class="countdown-date">Starts on: <span class="font-semibold">{{ nextEvent.dateText }}</span></p>
|
||||
<p class="countdown-date">{{ t('home.startsOn') }} <span class="font-semibold">{{ nextEvent.dateText }}</span></p>
|
||||
|
||||
<div v-if="followingEvents.length > 0" class="upcoming-events-section">
|
||||
<h3 class="upcoming-events-title">Upcoming Events</h3>
|
||||
<h3 class="upcoming-events-title">{{ t('home.upcomingEvents') }}</h3>
|
||||
<div class="space-y-4">
|
||||
<div v-for="event in followingEvents" :key="event.name" class="upcoming-event-item">
|
||||
<span class="font-bold text-gray-800">{{ event.name }}</span>
|
||||
@@ -46,8 +44,8 @@
|
||||
</div>
|
||||
<div class="featured-content">
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<span class="featured-badge">Featured Game</span>
|
||||
<span :class="`status-badge status-${highlightedSoftware.software.status}`">{{ highlightedSoftware.software.status }}</span>
|
||||
<span class="featured-badge">{{ t('home.featuredGame') }}</span>
|
||||
<span :class="`status-badge status-${highlightedSoftware.software.status}`">{{ t(`common.status.${highlightedSoftware.software.status}`) }}</span>
|
||||
<span v-if="highlightedStableRelease" class="featured-version-badge">{{ highlightedStableRelease.version }}</span>
|
||||
</div>
|
||||
<h2 class="featured-title">{{ highlightedSoftware.software.title }}</h2>
|
||||
@@ -59,9 +57,9 @@
|
||||
:href="highlightedStableRelease.htmlFolderPath"
|
||||
target="_blank"
|
||||
class="featured-btn-play"
|
||||
>▶ Play in Browser</a>
|
||||
>{{ t('home.playInBrowser') }}</a>
|
||||
<RouterLink :to="`/catalog/${highlightedSoftware.software.name}`" class="featured-btn-secondary">
|
||||
View Project Details
|
||||
{{ t('home.viewProjectDetails') }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
@@ -78,10 +76,10 @@
|
||||
<div class="yt-status-blob">
|
||||
<div class="yt-status-dot"></div>
|
||||
</div>
|
||||
<span class="yt-label-text">Latest from YouTube</span>
|
||||
<span class="yt-label-text">{{ t('home.latestFromYoutube') }}</span>
|
||||
</div>
|
||||
<a href="https://www.youtube.com/@teletypegames" target="_blank" class="yt-channel-link">
|
||||
Visit Channel ↗
|
||||
{{ t('home.visitChannel') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -96,7 +94,7 @@
|
||||
<div class="text-[11px] text-slate-500 text-center px-4 font-bold uppercase tracking-tighter">{{ ytError }}</div>
|
||||
</div>
|
||||
<div v-else-if="ytState === 'no-config'" class="state-overlay absolute inset-0 flex items-center justify-center bg-slate-950">
|
||||
<div class="text-slate-500 text-xs">Missing API Configuration</div>
|
||||
<div class="text-slate-500 text-xs">{{ t('common.missingApiConfig') }}</div>
|
||||
</div>
|
||||
<iframe
|
||||
v-else-if="ytVideoId"
|
||||
@@ -110,7 +108,7 @@
|
||||
|
||||
<div v-if="ytVideoId" class="yt-info-sidebar">
|
||||
<div class="mb-auto">
|
||||
<span class="yt-new-tag">New Release</span>
|
||||
<span class="yt-new-tag">{{ t('home.newRelease') }}</span>
|
||||
<h3 class="yt-video-title">{{ ytTitle }}</h3>
|
||||
<div class="yt-stats-row">
|
||||
<span v-if="ytPublishDate">📅 {{ ytPublishDate }}</span>
|
||||
@@ -120,7 +118,7 @@
|
||||
|
||||
<div class="mt-6">
|
||||
<a :href="`https://www.youtube.com/watch?v=${ytVideoId}`" target="_blank" class="yt-play-button">
|
||||
<span class="text-xl">▶</span> Watch on YouTube
|
||||
<span class="text-xl">▶</span> {{ t('home.watchOnYoutube') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -134,10 +132,10 @@
|
||||
<div class="nav-card-icon bg-purple-50 group-hover:bg-purple-100">
|
||||
<span class="text-3xl">🎮</span>
|
||||
</div>
|
||||
<h2 class="nav-card-title">Catalog</h2>
|
||||
<p class="nav-card-desc">Here you can find our games. Discover our creations for TIC-80 and other platforms, many of which you can try directly in your browser.</p>
|
||||
<h2 class="nav-card-title">{{ t('home.catalog.title') }}</h2>
|
||||
<p class="nav-card-desc">{{ t('home.catalog.desc') }}</p>
|
||||
<RouterLink to="/catalog" class="btn-primary bg-purple-600 hover:bg-purple-700 text-white hover:shadow-purple-200">
|
||||
Browse Games
|
||||
{{ t('home.catalog.btn') }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
|
||||
@@ -145,10 +143,10 @@
|
||||
<div class="nav-card-icon bg-green-50 group-hover:bg-green-100">
|
||||
<span class="text-3xl">📚</span>
|
||||
</div>
|
||||
<h2 class="nav-card-title">Wiki</h2>
|
||||
<p class="nav-card-desc">We gather our public interest development knowledge here. Read through technical descriptions and development logs.</p>
|
||||
<h2 class="nav-card-title">{{ t('home.wiki.title') }}</h2>
|
||||
<p class="nav-card-desc">{{ t('home.wiki.desc') }}</p>
|
||||
<a href="https://wiki.teletype.hu" target="_blank" rel="noopener noreferrer" class="btn-primary bg-green-600 hover:bg-green-700 text-white hover:shadow-green-200">
|
||||
Knowledge Base
|
||||
{{ t('home.wiki.btn') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -156,10 +154,10 @@
|
||||
<div class="nav-card-icon bg-slate-50 group-hover:bg-slate-100">
|
||||
<span class="text-3xl">💻</span>
|
||||
</div>
|
||||
<h2 class="nav-card-title">Git Repos</h2>
|
||||
<p class="nav-card-desc">All our projects are open source. Browse our code, study our solutions, or even participate in the development.</p>
|
||||
<h2 class="nav-card-title">{{ t('home.git.title') }}</h2>
|
||||
<p class="nav-card-desc">{{ t('home.git.desc') }}</p>
|
||||
<a href="https://git.teletype.hu" target="_blank" rel="noopener noreferrer" class="btn-primary bg-slate-800 hover:bg-slate-900 text-white hover:shadow-slate-200">
|
||||
Gitea
|
||||
{{ t('home.git.btn') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -167,10 +165,10 @@
|
||||
<div class="nav-card-icon bg-red-50 group-hover:bg-red-100">
|
||||
<span class="text-3xl">📺</span>
|
||||
</div>
|
||||
<h2 class="nav-card-title">YouTube</h2>
|
||||
<p class="nav-card-desc">Watch our development vlogs, gameplay videos, and tutorials on our official YouTube channel.</p>
|
||||
<h2 class="nav-card-title">{{ t('home.youtube.title') }}</h2>
|
||||
<p class="nav-card-desc">{{ t('home.youtube.desc') }}</p>
|
||||
<a href="https://www.youtube.com/@teletypegames" target="_blank" rel="noopener noreferrer" class="btn-primary bg-red-600 hover:bg-red-700 text-white hover:shadow-red-200">
|
||||
Watch on YouTube
|
||||
{{ t('home.youtube.btn') }}
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
@@ -179,7 +177,7 @@
|
||||
<div class="mb-12 mt-12 bg-white rounded-2xl border border-indigo-100 p-6 shadow-sm flex items-center gap-4">
|
||||
<div class="w-12 h-12 rounded-full bg-indigo-50 flex items-center justify-center text-2xl flex-shrink-0">🤖</div>
|
||||
<div class="flex-grow text-slate-600 text-sm md:text-base italic">
|
||||
<strong>Note:</strong> Our HowTo-s and blog posts are written by AI with human supervision.
|
||||
<strong>Note:</strong> {{ t('home.note') }}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@@ -190,10 +188,13 @@
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useEventStore } from '../../stores/event.store'
|
||||
import { useSoftwareStore } from '../../stores/software.store'
|
||||
import { useYoutubeStore } from '../../stores/youtube.store'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const eventStore = useEventStore()
|
||||
const { nextEvent, followingEvents, countdownText } = storeToRefs(eventStore)
|
||||
|
||||
|
||||
@@ -7,15 +7,13 @@
|
||||
</div>
|
||||
|
||||
<div class="hero-container">
|
||||
<div class="hero-badge">Knowledge Base</div>
|
||||
<div class="hero-badge">{{ t('howtos.badge') }}</div>
|
||||
<h1 class="hero-title">
|
||||
Tech <span class="text-transparent bg-clip-text bg-gradient-to-r from-indigo-400 to-purple-400">HowTo Center</span>
|
||||
</h1>
|
||||
<p class="hero-subtitle mb-10">
|
||||
The latest documentation, technical guides, and development logs from our knowledge base.
|
||||
</p>
|
||||
<p class="hero-subtitle mb-10">{{ t('howtos.subtitle') }}</p>
|
||||
<a :href="WIKI_BASE" target="_blank" class="btn-hero-indigo">
|
||||
Knowledge Base
|
||||
{{ t('howtos.knowledgeBase') }}
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
@@ -24,15 +22,15 @@
|
||||
<div v-if="error" class="error-banner" role="alert">
|
||||
<span class="text-2xl">⚠️</span>
|
||||
<div>
|
||||
<h3 class="error-banner-title">Failed to connect to Wiki</h3>
|
||||
<h3 class="error-banner-title">{{ t('howtos.errorTitle') }}</h3>
|
||||
<p class="error-banner-desc">{{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="!loading && recentPages.length === 0" class="empty-state">
|
||||
<div class="empty-state-icon">📭</div>
|
||||
<h2 class="empty-state-title">No pages found</h2>
|
||||
<p class="empty-state-desc">It seems like there aren't any public pages available on the wiki at the moment.</p>
|
||||
<h2 class="empty-state-title">{{ t('howtos.noPagesTitle') }}</h2>
|
||||
<p class="empty-state-desc">{{ t('howtos.noPagesDesc') }}</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="card-grid">
|
||||
@@ -47,7 +45,7 @@
|
||||
<div class="howto-card-timestamp">
|
||||
<span v-if="isNew(page.createdAt)" class="new-badge">
|
||||
<span class="new-dot"></span>
|
||||
New
|
||||
{{ t('howtos.new') }}
|
||||
</span>
|
||||
<span>{{ formatDateTime(page.updatedAt) }}</span>
|
||||
</div>
|
||||
@@ -56,18 +54,18 @@
|
||||
<h2 class="howto-card-title">{{ page.title }}</h2>
|
||||
|
||||
<p v-if="page.description" class="howto-card-desc">{{ page.description }}</p>
|
||||
<div v-else class="howto-card-no-desc">No description provided.</div>
|
||||
<div v-else class="howto-card-no-desc">{{ t('howtos.noDesc') }}</div>
|
||||
|
||||
<div class="howto-card-footer">
|
||||
<span class="howto-card-path">{{ page.path }}</span>
|
||||
<span class="howto-card-read-link">Read <span class="text-lg">→</span></span>
|
||||
<span class="howto-card-read-link">{{ t('howtos.read') }} <span class="text-lg">→</span></span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div v-if="!error && recentPages.length > 0" class="howtos-footer">
|
||||
<a :href="WIKI_BASE" target="_blank" class="browse-wiki-btn">
|
||||
Browse Wiki Home
|
||||
{{ t('howtos.browseWiki') }}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
@@ -80,10 +78,13 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { formatDateTime } from '../../lib/dateFormat'
|
||||
import { WIKI_BASE } from '../../api/wiki.api'
|
||||
import { useHowtosStore } from '../../stores/howtos.store'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const store = useHowtosStore()
|
||||
const { pages: recentPages, loading, error } = storeToRefs(store)
|
||||
const { isNew } = store
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
<template>
|
||||
<header class="hero-section-gradient from-purple-600 to-blue-700 py-20 text-white">
|
||||
<div class="hero-container text-center">
|
||||
<h1 class="hero-title mb-6">Our Team</h1>
|
||||
<p class="hero-subtitle mb-10 text-purple-100">
|
||||
Meet the brilliant minds behind Teletype Games.
|
||||
</p>
|
||||
<h1 class="hero-title mb-6">{{ t('team.title') }}</h1>
|
||||
<p class="hero-subtitle mb-10 text-purple-100">{{ t('team.subtitle') }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -26,8 +24,11 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useMemberStore } from '../../stores/member.store'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const store = useMemberStore()
|
||||
const { members } = storeToRefs(store)
|
||||
const { resolvedAvatarUrl } = store
|
||||
|
||||
Reference in New Issue
Block a user