style: add prettier configuration and format code

This commit is contained in:
2025-03-07 10:33:46 +01:00
parent 4f96206b8a
commit 540c70216c
24 changed files with 8885 additions and 3810 deletions

View File

@ -0,0 +1,8 @@
{
"semi": true,
"tabWidth": 4,
"trailingComma": "es5",
"printWidth": 200,
"bracketSpacing": true,
"arrowParens": "always"
}

View File

@ -42,6 +42,6 @@ If you have state that's important to retain within a component, consider creati
```ts
// store.ts
// An extremely simple external store
import { writable } from 'svelte/store'
export default writable(0)
import { writable } from "svelte/store";
export default writable(0);
```

View File

@ -1,12 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/hexagon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/hexagon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

5082
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +1,43 @@
{
"name": "hexdeck-frontend",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tailwindcss/forms": "^0.5.9",
"@tailwindcss/typography": "^0.5.15",
"@tailwindcss/vite": "^4.0.0",
"@tsconfig/svelte": "^5.0.4",
"flowbite": "^3.1.2",
"flowbite-svelte": "^0.48.4",
"flowbite-svelte-icons": "^2.0.2",
"sass-embedded": "^1.85.1",
"svelte": "^5.22.5",
"svelte-check": "^4.1.4",
"tailwindcss": "^4.0.0",
"typescript": "~5.8.2",
"vite": "^6.2.0"
},
"dependencies": {
"@roxi/routify": "3.0.0-next.254",
"@tailwindcss/vite": "^4.0.10",
"lucide-svelte": "^0.477.0",
"routify": "^2.0.1",
"socket.io-client": "^4.8.1",
"svelte-exmarkdown": "^4.0.3",
"svelte-i18n": "^4.0.1",
"tailwindcss": "^4.0.10"
},
"pnpm": {
"onlyBuiltDependencies": [
"esbuild"
]
}
}
"name": "hexdeck-frontend",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tailwindcss/forms": "^0.5.9",
"@tailwindcss/typography": "^0.5.15",
"@tailwindcss/vite": "^4.0.0",
"@tsconfig/svelte": "^5.0.4",
"flowbite": "^3.1.2",
"flowbite-svelte": "^0.48.4",
"flowbite-svelte-icons": "^2.0.2",
"prettier": "3.5.3",
"sass-embedded": "^1.85.1",
"svelte": "^5.22.5",
"svelte-check": "^4.1.4",
"tailwindcss": "^4.0.0",
"typescript": "~5.8.2",
"vite": "^6.2.0"
},
"dependencies": {
"@roxi/routify": "3.0.0-next.254",
"@tailwindcss/vite": "^4.0.10",
"lucide-svelte": "^0.477.0",
"routify": "^2.0.1",
"socket.io-client": "^4.8.1",
"svelte-exmarkdown": "^4.0.3",
"svelte-i18n": "^4.0.1",
"tailwindcss": "^4.0.10"
},
"pnpm": {
"onlyBuiltDependencies": [
"esbuild"
]
}
}

6171
frontend/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,88 +1,90 @@
@theme inline {
--color-primary-50: color-mix(in srgb, var(--primary) 10%, white);
--color-primary-100: color-mix(in srgb, var(--primary) 20%, white);
--color-primary-200: color-mix(in srgb, var(--primary) 30%, white);
--color-primary-300: color-mix(in srgb, var(--primary) 40%, white);
--color-primary-400: color-mix(in srgb, var(--primary) 50%, white);
--color-primary-500: color-mix(in srgb, var(--primary) 60%, white);
--color-primary-600: color-mix(in srgb, var(--primary) 70%, white);
--color-primary-700: color-mix(in srgb, var(--primary) 80%, white);
--color-primary-800: color-mix(in srgb, var(--primary) 90%, white);
--color-primary-900: var(--primary);
--color-primary-950: color-mix(in srgb, var(--primary) 90%, black);
--color-primary-50: color-mix(in srgb, var(--primary) 10%, white);
--color-primary-100: color-mix(in srgb, var(--primary) 20%, white);
--color-primary-200: color-mix(in srgb, var(--primary) 30%, white);
--color-primary-300: color-mix(in srgb, var(--primary) 40%, white);
--color-primary-400: color-mix(in srgb, var(--primary) 50%, white);
--color-primary-500: color-mix(in srgb, var(--primary) 60%, white);
--color-primary-600: color-mix(in srgb, var(--primary) 70%, white);
--color-primary-700: color-mix(in srgb, var(--primary) 80%, white);
--color-primary-800: color-mix(in srgb, var(--primary) 90%, white);
--color-primary-900: var(--primary);
--color-primary-950: color-mix(in srgb, var(--primary) 90%, black);
--color-secondary-50: color-mix(in srgb, var(--secondary) 10%, white);
--color-secondary-100: color-mix(in srgb, var(--secondary) 20%, white);
--color-secondary-200: color-mix(in srgb, var(--secondary) 30%, white);
--color-secondary-300: color-mix(in srgb, var(--secondary) 40%, white);
--color-secondary-400: color-mix(in srgb, var(--secondary) 50%, white);
--color-secondary-500: color-mix(in srgb, var(--secondary) 60%, white);
--color-secondary-600: color-mix(in srgb, var(--secondary) 70%, white);
--color-secondary-700: color-mix(in srgb, var(--secondary) 80%, white);
--color-secondary-800: color-mix(in srgb, var(--secondary) 90%, white);
--color-secondary-900: var(--secondary);
--color-secondary-950: color-mix(in srgb, var(--secondary) 90%, black);
--color-secondary-50: color-mix(in srgb, var(--secondary) 10%, white);
--color-secondary-100: color-mix(in srgb, var(--secondary) 20%, white);
--color-secondary-200: color-mix(in srgb, var(--secondary) 30%, white);
--color-secondary-300: color-mix(in srgb, var(--secondary) 40%, white);
--color-secondary-400: color-mix(in srgb, var(--secondary) 50%, white);
--color-secondary-500: color-mix(in srgb, var(--secondary) 60%, white);
--color-secondary-600: color-mix(in srgb, var(--secondary) 70%, white);
--color-secondary-700: color-mix(in srgb, var(--secondary) 80%, white);
--color-secondary-800: color-mix(in srgb, var(--secondary) 90%, white);
--color-secondary-900: var(--secondary);
--color-secondary-950: color-mix(in srgb, var(--secondary) 90%, black);
--color-tertiary-50: color-mix(in srgb, var(--tertiary) 10%, white);
--color-tertiary-100: color-mix(in srgb, var(--tertiary) 20%, white);
--color-tertiary-200: color-mix(in srgb, var(--tertiary) 30%, white);
--color-tertiary-300: color-mix(in srgb, var(--tertiary) 40%, white);
--color-tertiary-400: color-mix(in srgb, var(--tertiary) 50%, white);
--color-tertiary-500: color-mix(in srgb, var(--tertiary) 60%, white);
--color-tertiary-600: color-mix(in srgb, var(--tertiary) 70%, white);
--color-tertiary-700: color-mix(in srgb, var(--tertiary) 80%, white);
--color-tertiary-800: color-mix(in srgb, var(--tertiary) 90%, white);
--color-tertiary-900: var(--tertiary);
--color-tertiary-950: color-mix(in srgb, var(--tertiary) 90%, black);
--color-tertiary-50: color-mix(in srgb, var(--tertiary) 10%, white);
--color-tertiary-100: color-mix(in srgb, var(--tertiary) 20%, white);
--color-tertiary-200: color-mix(in srgb, var(--tertiary) 30%, white);
--color-tertiary-300: color-mix(in srgb, var(--tertiary) 40%, white);
--color-tertiary-400: color-mix(in srgb, var(--tertiary) 50%, white);
--color-tertiary-500: color-mix(in srgb, var(--tertiary) 60%, white);
--color-tertiary-600: color-mix(in srgb, var(--tertiary) 70%, white);
--color-tertiary-700: color-mix(in srgb, var(--tertiary) 80%, white);
--color-tertiary-800: color-mix(in srgb, var(--tertiary) 90%, white);
--color-tertiary-900: var(--tertiary);
--color-tertiary-950: color-mix(in srgb, var(--tertiary) 90%, black);
}
@layer base {
button,
[role='button'] {
cursor: pointer;
}
button,
[role="button"] {
cursor: pointer;
}
}
body {
margin: 0;
color: var(--default-element-color);
background-color: var(--default-background-color);
transition: color 0.4s ease, background-color 0.2s ease;
margin: 0;
color: var(--default-element-color);
background-color: var(--default-background-color);
transition:
color 0.4s ease,
background-color 0.2s ease;
}
:root {
font-family: "Lexend Deca", serif;
font-optical-sizing: auto;
line-height: 1.5;
font-weight: 400;
font-family: "Lexend Deca", serif;
font-optical-sizing: auto;
line-height: 1.5;
font-weight: 400;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
--primary: #d5b6ff;
--secondary: #ffb6f5;
--tertiary: #08aeea;
--primary: #d5b6ff;
--secondary: #ffb6f5;
--tertiary: #08aeea;
--default-element-color: #213547;
--default-background-color: #ffffff;
--default-element-color: #213547;
--default-background-color: #ffffff;
}
body.dark-theme {
--primary: #53346a;
--secondary: #710cff;
--tertiary: #0b465c;
--primary: #53346a;
--secondary: #710cff;
--tertiary: #0b465c;
--default-element-color: rgba(255, 255, 255, 0.87);
--default-background-color: oklch(0.279 0.041 260.031);
--default-element-color: rgba(255, 255, 255, 0.87);
--default-background-color: oklch(0.279 0.041 260.031);
}
body.light-theme {
--primary: #d5b6ff;
--secondary: #ffb6f5;
--tertiary: #08aeea;
--primary: #d5b6ff;
--secondary: #ffb6f5;
--tertiary: #08aeea;
--default-element-color: #213547;
--default-background-color: #ffffff;
}
--default-element-color: #213547;
--default-background-color: #ffffff;
}

View File

@ -1,103 +1,103 @@
{
"page_name": "HexDeck",
"header": {
"theme_btn": {
"tooltip": "Thema wechseln: {current_theme}",
"dark": "Dunkel",
"light": "Hell",
"system": "System"
"page_name": "HexDeck",
"header": {
"theme_btn": {
"tooltip": "Thema wechseln: {current_theme}",
"dark": "Dunkel",
"light": "Hell",
"system": "System"
}
},
"footer": {
"imprint": "Impressum",
"github": "GitHub"
},
"404": {
"404_page_not_found": "404 - Seite nicht gefunden",
"page_not_found": "Die Seite {page} konnte nicht gefunden werden."
},
"imprint": {
"title": "Impressum",
"something_went_wrong": "Etwas ist schief gelaufen",
"timeout_while_loading": "Zeitüberschreitung beim Laden",
"retry": "Erneut versuchen",
"go_back": "Zurück"
},
"landing_page": {
"sub_title": "Multiplayer, kostenlos, für alle",
"connect_room": {
"rejoin_last_room": "Letztes Spiel erneut beitreten",
"join_last_room": "Letztem Raum beitreten",
"enter_room_code": "Raumcode eingeben",
"join_room": "Beitreten",
"enter_room_code_to_join": "Bitte geben Sie einen Raumcode ein, um beizutreten",
"or": "oder",
"create_a_room": "Einen Raum erstellen"
},
"open_source_container": {
"title": "Open Source",
"content": "Der Quellcode dieses Spiels ist auf GitHub verfügbar",
"github": "GitHub"
},
"stats_container": {
"title": "Statistiken",
"online_player_count": "Aktuelle Spieler: {count}",
"current_game_rooms": "Aktuelle Spiele: {count}",
"games_played": "Gespielte Spiele: {count}",
"no_data": "Keine Daten"
},
"show_footer": "Footer anzeigen"
},
"lobby": {
"search_player": "Spieler suchen...",
"kick_player": "Spieler entfernen",
"confirm_kick_player_message": "Möchten Sie den Spieler {player_name} wirklich entfernen?",
"confirm_kick_player": "Entfernen",
"rename_yourself": "Sich selbst umbenennen",
"rename_player": "Spieler umbenennen",
"regenerate_join_code": "Beitrittscode neu generieren",
"copy_join_code": "Beitrittscode kopieren",
"room_join_code": "Raum Beitrittscode",
"copy_code": "Code kopieren",
"copy_join_link": "Link kopieren",
"leave_game": "Spiel verlassen",
"confirm_leave_message": "Möchten Sie das Spiel wirklich verlassen?",
"confirm_leave": "Ja, verlassen",
"cancel": "Abbrechen",
"start_game": "Spiel starten",
"copied": "Kopiert",
"player_name": "Spielername",
"status": "Status",
"host": "Host",
"you": "Du"
},
"player_status": {
"connected": "Verbunden",
"disconnected": "Getrennt"
},
"game_status": {
"game_status": "Spielstatus: {game_status}",
"lobby": "Lobby",
"running": "Läuft",
"ended": "Beendet"
},
"error_messages": {
"no_room_found": "Kein Raum mit diesem Code gefunden",
"request_timeout": "Internet fehlgeschlagen! (Zeitüberschreitung)",
"invalid_player": "Ungültiger Spieler",
"invalid_session": "Ungültige Sitzung",
"game_not_running": "Das Spiel läuft nicht",
"player_not_active": "Der Spieler ist nicht aktiv",
"insufficient_permission": "Unzureichende Berechtigung",
"username_taken": "Der Benutzername ist bereits vergeben",
"game_already_started": "Das Spiel hat bereits begonnen",
"missing_parameter": "Fehlender Parameter",
"invalid_card_index": "Ungültige Karte ausgewählt (Index außerhalb der Grenzen)",
"card_not_playable": "Die Karte ist nicht spielbar",
"card_not_updatable": "Die Karte ist nicht aktualisierbar",
"error_message": "Fehlermeldung: {error_message}"
},
"game_screen": {
"loading": "Laden"
}
},
"footer": {
"imprint": "Impressum",
"github": "GitHub"
},
"404": {
"404_page_not_found": "404 - Seite nicht gefunden",
"page_not_found": "Die Seite {page} konnte nicht gefunden werden."
},
"imprint": {
"title": "Impressum",
"something_went_wrong": "Etwas ist schief gelaufen",
"timeout_while_loading": "Zeitüberschreitung beim Laden",
"retry": "Erneut versuchen",
"go_back": "Zurück"
},
"landing_page": {
"sub_title": "Multiplayer, kostenlos, für alle",
"connect_room": {
"rejoin_last_room": "Letztes Spiel erneut beitreten",
"join_last_room": "Letztem Raum beitreten",
"enter_room_code": "Raumcode eingeben",
"join_room": "Beitreten",
"enter_room_code_to_join": "Bitte geben Sie einen Raumcode ein, um beizutreten",
"or": "oder",
"create_a_room": "Einen Raum erstellen"
},
"open_source_container": {
"title": "Open Source",
"content": "Der Quellcode dieses Spiels ist auf GitHub verfügbar",
"github": "GitHub"
},
"stats_container": {
"title": "Statistiken",
"online_player_count": "Aktuelle Spieler: {count}",
"current_game_rooms": "Aktuelle Spiele: {count}",
"games_played": "Gespielte Spiele: {count}",
"no_data": "Keine Daten"
},
"show_footer": "Footer anzeigen"
},
"lobby": {
"search_player": "Spieler suchen...",
"kick_player": "Spieler entfernen",
"confirm_kick_player_message": "Möchten Sie den Spieler {player_name} wirklich entfernen?",
"confirm_kick_player": "Entfernen",
"rename_yourself": "Sich selbst umbenennen",
"rename_player": "Spieler umbenennen",
"regenerate_join_code": "Beitrittscode neu generieren",
"copy_join_code": "Beitrittscode kopieren",
"room_join_code": "Raum Beitrittscode",
"copy_code": "Code kopieren",
"copy_join_link": "Link kopieren",
"leave_game": "Spiel verlassen",
"confirm_leave_message": "Möchten Sie das Spiel wirklich verlassen?",
"confirm_leave": "Ja, verlassen",
"cancel": "Abbrechen",
"start_game": "Spiel starten",
"copied": "Kopiert",
"player_name": "Spielername",
"status": "Status",
"host": "Host",
"you": "Du"
},
"player_status": {
"connected": "Verbunden",
"disconnected": "Getrennt"
},
"game_status": {
"game_status": "Spielstatus: {game_status}",
"lobby": "Lobby",
"running": "Läuft",
"ended": "Beendet"
},
"error_messages": {
"no_room_found": "Kein Raum mit diesem Code gefunden",
"request_timeout": "Internet fehlgeschlagen! (Zeitüberschreitung)",
"invalid_player": "Ungültiger Spieler",
"invalid_session": "Ungültige Sitzung",
"game_not_running": "Das Spiel läuft nicht",
"player_not_active": "Der Spieler ist nicht aktiv",
"insufficient_permission": "Unzureichende Berechtigung",
"username_taken": "Der Benutzername ist bereits vergeben",
"game_already_started": "Das Spiel hat bereits begonnen",
"missing_parameter": "Fehlender Parameter",
"invalid_card_index": "Ungültige Karte ausgewählt (Index außerhalb der Grenzen)",
"card_not_playable": "Die Karte ist nicht spielbar",
"card_not_updatable": "Die Karte ist nicht aktualisierbar",
"error_message": "Fehlermeldung: {error_message}"
},
"game_screen": {
"loading": "Laden"
}
}
}

View File

@ -1,105 +1,105 @@
{
"page_name": "HexDeck",
"header": {
"theme_btn": {
"tooltip": "Switch theme: {current_theme}",
"dark": "Dark",
"light": "Light",
"system": "System"
"page_name": "HexDeck",
"header": {
"theme_btn": {
"tooltip": "Switch theme: {current_theme}",
"dark": "Dark",
"light": "Light",
"system": "System"
}
},
"footer": {
"imprint": "Imprint",
"github": "GitHub"
},
"404": {
"404_page_not_found": "404 - Page not found",
"page_not_found": "The page {page} could not be found."
},
"imprint": {
"title": "Imprint",
"something_went_wrong": "Something went wrong",
"timeout_while_loading": "Timeout while loading",
"retry": "Retry",
"go_back": "Back"
},
"landing_page": {
"sub_title": "Multiplayer, free, for everyone",
"connect_room": {
"rejoin_last_room": "Rejoin last game",
"join_last_room": "Join last room",
"enter_room_code": "Enter a room code",
"join_room": "Join",
"enter_room_code_to_join": "Please enter a room code to join",
"or": "or",
"create_a_room": "Create a room"
},
"open_source_container": {
"title": "Open Source",
"content": "The Source Code of this game is available on GitHub",
"github": "GitHub"
},
"stats_container": {
"title": "Stats",
"online_player_count": "Current player: {count}",
"current_game_rooms": "Current games: {count}",
"games_played": "Games played: {count}",
"no_data": "No data"
},
"show_footer": "Show footer"
},
"lobby": {
"search_player": "Search player...",
"kick_player": "Kick player",
"confirm_kick_player_message": "Do you really want to kick the player {player_name}?",
"confirm_kick_player": "Kick",
"rename_yourself": "Rename yourself",
"rename_player": "Rename player",
"regenerate_join_code": "Regenerate join code",
"copy_join_code": "Copy join code",
"room_join_code": "Room Join Code",
"copy_code": "Copy Code",
"copy_join_link": "Copy Link",
"leave_game": "Leave game",
"confirm_leave_message": "Do you really want to leave the game?",
"confirm_leave": "Yes, leave",
"cancel": "Cancel",
"start_game": "Start game",
"copied": "Copied",
"player_name": "Player Name",
"status": "Status",
"host": "Host",
"you": "You",
"player": "Player",
"return_to_game": "Return to game"
},
"player_status": {
"connected": "Connected",
"disconnected": "Disconnected"
},
"game_status": {
"game_status": "Game status:",
"lobby": "Lobby",
"running": "Running",
"ended": "Ended"
},
"error_messages": {
"no_room_found": "No room was found with this code",
"request_timeout": "Internet failed! (Timeout)",
"invalid_player": "Invalid player",
"invalid_session": "Invalid session",
"game_not_running": "The game is not running",
"player_not_active": "The player ist not active",
"insufficient_permission": "Insufficient permission",
"username_taken": "The username is already taken",
"game_already_started": "The game has already started",
"missing_parameter": "Missing parameter",
"invalid_card_index": "Invalid card selected (Index not in bounds)",
"card_not_playable": "The card is not playable",
"card_not_updatable": "The card is not updatable",
"error_message": "Error message: {error_message}"
},
"game_screen": {
"loading": "Loading"
}
},
"footer": {
"imprint": "Imprint",
"github": "GitHub"
},
"404": {
"404_page_not_found": "404 - Page not found",
"page_not_found": "The page {page} could not be found."
},
"imprint": {
"title": "Imprint",
"something_went_wrong": "Something went wrong",
"timeout_while_loading": "Timeout while loading",
"retry": "Retry",
"go_back": "Back"
},
"landing_page": {
"sub_title": "Multiplayer, free, for everyone",
"connect_room": {
"rejoin_last_room": "Rejoin last game",
"join_last_room": "Join last room",
"enter_room_code": "Enter a room code",
"join_room": "Join",
"enter_room_code_to_join": "Please enter a room code to join",
"or": "or",
"create_a_room": "Create a room"
},
"open_source_container": {
"title": "Open Source",
"content": "The Source Code of this game is available on GitHub",
"github": "GitHub"
},
"stats_container": {
"title": "Stats",
"online_player_count": "Current player: {count}",
"current_game_rooms": "Current games: {count}",
"games_played": "Games played: {count}",
"no_data": "No data"
},
"show_footer": "Show footer"
},
"lobby": {
"search_player": "Search player...",
"kick_player": "Kick player",
"confirm_kick_player_message": "Do you really want to kick the player {player_name}?",
"confirm_kick_player": "Kick",
"rename_yourself": "Rename yourself",
"rename_player": "Rename player",
"regenerate_join_code": "Regenerate join code",
"copy_join_code": "Copy join code",
"room_join_code": "Room Join Code",
"copy_code": "Copy Code",
"copy_join_link": "Copy Link",
"leave_game": "Leave game",
"confirm_leave_message": "Do you really want to leave the game?",
"confirm_leave": "Yes, leave",
"cancel": "Cancel",
"start_game": "Start game",
"copied": "Copied",
"player_name": "Player Name",
"status": "Status",
"host": "Host",
"you": "You",
"player": "Player",
"return_to_game": "Return to game"
},
"player_status": {
"connected": "Connected",
"disconnected": "Disconnected"
},
"game_status": {
"game_status": "Game status:",
"lobby": "Lobby",
"running": "Running",
"ended": "Ended"
},
"error_messages": {
"no_room_found": "No room was found with this code",
"request_timeout": "Internet failed! (Timeout)",
"invalid_player": "Invalid player",
"invalid_session": "Invalid session",
"game_not_running": "The game is not running",
"player_not_active": "The player ist not active",
"insufficient_permission": "Insufficient permission",
"username_taken": "The username is already taken",
"game_already_started": "The game has already started",
"missing_parameter": "Missing parameter",
"invalid_card_index": "Invalid card selected (Index not in bounds)",
"card_not_playable": "The card is not playable",
"card_not_updatable": "The card is not updatable",
"error_message": "Error message: {error_message}"
},
"game_screen": {
"loading": "Loading"
}
}
}

View File

@ -1,18 +1,18 @@
import { addMessages, register, init, getLocaleFromNavigator } from 'svelte-i18n';
import { addMessages, register, init, getLocaleFromNavigator } from "svelte-i18n";
import en from './en.json';
import de from './de.json';
import en from "./en.json";
import de from "./de.json";
addMessages('en', en);
addMessages('de', de);
addMessages("en", en);
addMessages("de", de);
register('en', () => import('./en.json'));
register('de', () => import('./de.json'));
register("en", () => import("./en.json"));
register("de", () => import("./de.json"));
const initialLocale = getLocaleFromNavigator();
console.log('Initial locale:', initialLocale);
console.log("Initial locale:", initialLocale);
init({
fallbackLocale: 'en',
initialLocale: initialLocale,
});
fallbackLocale: "en",
initialLocale: initialLocale,
});

View File

@ -1,12 +1,12 @@
@import url('https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@100..900&display=swap');
@import 'tailwindcss';
@import url("https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@100..900&display=swap");
@import "tailwindcss";
@plugin 'flowbite/plugin';
@custom-variant dark {
@media not print {
.dark & {
@slot;
}
.dark & {
@slot;
}
}
}
}
@source "../node_modules/flowbite-svelte/dist";
@import './app.scss';
@import "./app.scss";

View File

@ -1,11 +1,10 @@
import { mount } from 'svelte'
import './i18n/i18n'
import './index.css'
import App from './App.svelte'
import { mount } from "svelte";
import "./i18n/i18n";
import "./index.css";
import App from "./App.svelte";
const app = mount(App, {
target: document.getElementById('app')!,
})
export default app
target: document.getElementById("app")!,
});
export default app;

View File

@ -5,11 +5,10 @@
import { _ } from "svelte-i18n";
import { onMount } from "svelte";
import { GameState, sessionStore } from "../stores/sessionStore";
import { Button, Spinner, Tooltip } from "flowbite-svelte";
import { Spinner } from "flowbite-svelte";
import { SvelteDate } from "svelte/reactivity";
import { requestJoinRoom } from "../stores/roomStore";
import gameStore, { toggleLobbyOverlay } from "../stores/gameStore";
import { UsersRound } from "lucide-svelte";
import gameStore from "../stores/gameStore";
onMount(async () => {
// TODO: check if already connected to room, currently its overwriting the session
@ -31,9 +30,7 @@
{#if !$sessionStore.connected}
<div class="flex flex-row w-full mt-32 h-full justify-center items-center">
<div
class="flex flex-col items-center gap-6 p-7 md:flex-row md:gap-8 rounded-2xl"
>
<div class="flex flex-col items-center gap-6 p-7 md:flex-row md:gap-8 rounded-2xl">
<div>
<Spinner size="12" class="text-primary-100" />
</div>
@ -42,9 +39,7 @@
{$_("game_screen.loading")}
</span>
<span class="font-medium text-sky-500">
{$sessionStore.players?.find(
(player) => player.PlayerId == $sessionStore.userId,
)?.Username}
{$sessionStore.players?.find((player) => player.PlayerId == $sessionStore.userId)?.Username}
</span>
<span class="flex gap-2 font-medium text-gray-600 dark:text-gray-400">
<span>{new SvelteDate().toLocaleString()}</span>

View File

@ -88,11 +88,7 @@
}
.Header {
background: linear-gradient(
180deg,
var(--default-background-color) 30%,
transparent 100%
);
background: linear-gradient(180deg, var(--default-background-color) 30%, transparent 100%);
opacity: 1;
position: fixed;
height: 100px;
@ -103,11 +99,7 @@
}
.Header-bg {
background: linear-gradient(
180deg,
var(--primary) 50%,
transparent 100%
);
background: linear-gradient(180deg, var(--primary) 50%, transparent 100%);
z-index: -1;
margin: 0px;
position: absolute;

View File

@ -1,4 +1,4 @@
import { writable } from 'svelte/store';
import { writable } from "svelte/store";
interface GameState {
isLobbyOverlayShown: boolean;
@ -11,10 +11,10 @@ const initialState: GameState = {
const gameStore = writable<GameState>(initialState);
export const toggleLobbyOverlay = () => {
gameStore.update(state => ({
gameStore.update((state) => ({
...state,
isLobbyOverlayShown: !state.isLobbyOverlayShown,
}));
};
export default gameStore;
export default gameStore;

View File

@ -1,7 +1,7 @@
import { Gamepad2 } from 'lucide-svelte';
import { Gamepad2 } from "lucide-svelte";
const options = {
page_icon: Gamepad2,
}
};
export default options;
export default options;

View File

@ -1,5 +1,5 @@
import { writable } from 'svelte/store';
import { sessionStore } from './sessionStore';
import { writable } from "svelte/store";
import { sessionStore } from "./sessionStore";
export const loading = writable<"join" | "create" | false>(false);
export const join_error = writable<string | false>(false);
@ -143,4 +143,4 @@ export async function checkSessionData() {
rejoinRoomCode.set(lastSessionData.joinCode as string);
return;
}
}
}

View File

@ -1,303 +1,303 @@
import { writable, get } from 'svelte/store';
import { io, Socket } from 'socket.io-client';
import { writable, get } from "svelte/store";
import { io, Socket } from "socket.io-client";
export enum GameState {
Undefined = -1,
Lobby,
Running,
Ended
Undefined = -1,
Lobby,
Running,
Ended,
}
interface PlayerPermissionObj {
isHost: boolean;
isHost: boolean;
}
interface GameOptions { }
interface GameOptions {}
interface PlayerObj {
PlayerId: string;
Username: string;
Permissions: number;
IsConnected: boolean;
PlayerId: string;
Username: string;
Permissions: number;
IsConnected: boolean;
}
interface SessionData {
roomId: string | null;
joinCode: string | null;
gameOptions: GameOptions;
players: Array<PlayerObj>;
cardDeckId: string | null;
gameState: GameState;
socket: Socket | null;
connected: boolean;
userId: string | null;
messages: string[];
sessionToken: string | null;
roomId: string | null;
joinCode: string | null;
gameOptions: GameOptions;
players: Array<PlayerObj>;
cardDeckId: string | null;
gameState: GameState;
socket: Socket | null;
connected: boolean;
userId: string | null;
messages: string[];
sessionToken: string | null;
}
interface RoomInfoObj {
RoomId: string;
JoinCode: string;
TopCard: any;
GameState: GameState;
CardDeckId: number;
Winner?: string;
Players: PlayerObj[];
RoomId: string;
JoinCode: string;
TopCard: any;
GameState: GameState;
CardDeckId: number;
Winner?: string;
Players: PlayerObj[];
}
interface StatusInfoObj {
IsError: boolean;
StatusCode: string;
Message: string;
IsError: boolean;
StatusCode: string;
Message: string;
}
class SessionManager {
private store = writable<SessionData>({
roomId: null,
joinCode: null,
gameState: -1,
gameOptions: {},
players: [],
cardDeckId: null,
socket: null,
connected: false,
userId: null,
messages: [],
sessionToken: null,
});
private socket: Socket | null = null;
constructor() {
const storedSessionIds = this.getStoredSessionIds();
if (storedSessionIds) {
console.info(`Found stored session: ${JSON.stringify(storedSessionIds)}`);
// this.connect(storedSessionIds.sessionToken, storedSessionIds.userId);
}
}
getState() {
return get(this.store);
}
startGame() {
this.socket?.emit("StartGame");
}
hasSessionData(): boolean {
const state = this.getState();
if (state.sessionToken && state.userId) return true;
const sessionIds = localStorage.getItem('currentSessionIds');
if (!sessionIds) return false;
const sessionIdsJson = JSON.parse(sessionIds);
return typeof sessionIdsJson.userId === "string" && typeof sessionIdsJson.sessionToken === "string";
}
private checkPermissionBit(permissionNumber: number, bitIndex: number): boolean {
return (permissionNumber & (1 << bitIndex)) > 0;
}
getPlayerPermissions(PlayerId?: string): PlayerPermissionObj {
if (!PlayerId) PlayerId = this.getState().userId ?? undefined;
const playerPermissionNumber: number = this.getState().players?.find((player) => player.PlayerId == PlayerId)?.Permissions ?? 0;
return {
isHost: this.checkPermissionBit(playerPermissionNumber, 0)
};
}
subscribe = this.store.subscribe;
private getStoredSessionIds(): { sessionToken: string, userId: string } | null {
if (typeof window === 'undefined') return null;
const sessionIds = localStorage.getItem('currentSessionIds');
if (!sessionIds) return null;
const sessionIdsJson = JSON.parse(sessionIds);
if (typeof sessionIdsJson.userId !== "string" || typeof sessionIdsJson.sessionToken !== "string") {
return null;
}
return { sessionToken: sessionIdsJson.sessionToken, userId: sessionIdsJson.userId };
}
private saveSessionIds(sessionToken: string, userId: string) {
if (typeof window !== 'undefined') {
localStorage.setItem('currentSessionIds', JSON.stringify({ sessionToken, userId, joinCode: this.getState().joinCode }));
}
}
private saveJoinCode() {
const sessionIds = localStorage.getItem('currentSessionIds');
if (!sessionIds) return;
const sessionIdsJson = JSON.parse(sessionIds);
localStorage.setItem('currentSessionIds', JSON.stringify({ sessionToken: sessionIdsJson.sessionToken, userId: sessionIdsJson.userId, joinCode: this.getState().joinCode }));
}
private clearSessionIds() {
if (typeof window !== 'undefined') {
const sessionIds = localStorage.getItem('currentSessionIds');
if (!sessionIds) return;
const sessionIdsJson = JSON.parse(sessionIds);
const lastSessionData = { joinCode: sessionIdsJson.joinCode };
localStorage.setItem('lastSessionIds', JSON.stringify(lastSessionData));
localStorage.removeItem('currentSessionIds');
}
}
isConnected(): boolean {
return this.socket?.connected ?? false;
}
hasRoomData(): boolean {
return get(this.store).gameState != -1;
}
getUserId(): string | undefined {
return this.getState().userId ?? undefined;
}
getUser(playerId?: string): PlayerObj | undefined {
if (!playerId) playerId = this.getUserId();
return this.getState().players.find((player) => player.PlayerId == playerId);
}
kickPlayer(playerId: string) {
if (!this.getPlayerPermissions().isHost) return;
this.socket?.emit("KickPlayer", JSON.stringify({ PlayerId: playerId }));
}
renamePlayer(playerId: string | undefined, newName: string) {
if (!playerId) playerId = this.getUserId();
if (!this.getPlayerPermissions().isHost && playerId != this.getUserId()) return;
this.socket?.emit("UpdatePlayer", JSON.stringify({ PlayerId: playerId, Username: newName }));
}
isCurrentPlayer(playerId: string): boolean {
return this.getState().userId == playerId;
}
connect(sessionToken?: string, userId?: string) {
if (!sessionToken) sessionToken = this.getState().sessionToken || undefined;
if (!userId) userId = this.getState().userId || undefined;
if (!sessionToken || !userId) {
const storedSessionIds = this.getStoredSessionIds();
if (!sessionToken) sessionToken = storedSessionIds?.sessionToken;
if (!userId) userId = storedSessionIds?.userId;
}
if (this.socket) {
console.warn(`Socket already connected! Rejecting new connection to ${sessionToken}`);
return;
}
this.socket = io({
transports: ['websocket'],
query: { sessionToken },
private store = writable<SessionData>({
roomId: null,
joinCode: null,
gameState: -1,
gameOptions: {},
players: [],
cardDeckId: null,
socket: null,
connected: false,
userId: null,
messages: [],
sessionToken: null,
});
this.setupSocketEventHandlers(sessionToken, userId);
}
private socket: Socket | null = null;
private setupSocketEventHandlers(sessionToken: string, userId: string) {
this.socket?.on('connect', () => this.handleConnect(sessionToken, userId));
this.socket?.on('disconnect', this.handleDisconnect.bind(this));
this.socket?.on('Status', this.handleStatus.bind(this));
this.socket?.on('RoomInfo', this.handleRoomInfo.bind(this));
this.socket?.on('error', this.handleError.bind(this));
}
private handleConnect(sessionToken: string, userId: string) {
console.info('Connected to room');
this.saveSessionIds(sessionToken, userId);
window.history.replaceState({}, "", "/Game");
this.store.update((state) => ({
...state,
socket: this.socket,
userId,
connected: true,
sessionToken,
}));
}
private handleDisconnect() {
console.info('Disconnected from server');
this.store.update((state) => ({ ...state, connected: false }));
}
private handleStatus(message: StatusInfoObj) {
console.log("Status: ", message);
if (message.IsError && message.StatusCode !== "connection_from_different_socket") {
this.leaveRoom();
constructor() {
const storedSessionIds = this.getStoredSessionIds();
if (storedSessionIds) {
console.info(`Found stored session: ${JSON.stringify(storedSessionIds)}`);
// this.connect(storedSessionIds.sessionToken, storedSessionIds.userId);
}
}
if (message.IsError) {
this.socket = null;
window.history.replaceState({}, "", "/");
}
this.store.update((state) => ({
...state,
messages: [...state.messages, message],
}));
}
private handleRoomInfo(message: RoomInfoObj) {
console.log("RoomInfo: ", message);
this.store.update((state) => ({
...state,
roomId: message.RoomId,
joinCode: message.JoinCode,
gameState: message.GameState,
cardDeckId: message.CardDeckId,
players: message.Players,
}));
this.saveJoinCode();
this.store.update((state) => ({
...state,
messages: [...state.messages, message],
}));
}
private handleError(error: string) {
console.error('Socket error:', error);
}
sendMessage(message: string) {
if (this.socket && message.trim()) {
this.socket.emit('event', message);
getState() {
return get(this.store);
}
}
leaveRoom() {
console.log("leave room");
if (this.socket) {
this.socket.disconnect();
this.socket = null;
startGame() {
this.socket?.emit("StartGame");
}
if (this.getState().sessionToken) {
fetch(`/api/room/leave`, {
method: "POST",
body: JSON.stringify({
SessionToken: this.getState().sessionToken
}),
headers: {
"Content-Type": "application/json",
},
});
hasSessionData(): boolean {
const state = this.getState();
if (state.sessionToken && state.userId) return true;
const sessionIds = localStorage.getItem("currentSessionIds");
if (!sessionIds) return false;
const sessionIdsJson = JSON.parse(sessionIds);
return typeof sessionIdsJson.userId === "string" && typeof sessionIdsJson.sessionToken === "string";
}
private checkPermissionBit(permissionNumber: number, bitIndex: number): boolean {
return (permissionNumber & (1 << bitIndex)) > 0;
}
getPlayerPermissions(PlayerId?: string): PlayerPermissionObj {
if (!PlayerId) PlayerId = this.getState().userId ?? undefined;
const playerPermissionNumber: number = this.getState().players?.find((player) => player.PlayerId == PlayerId)?.Permissions ?? 0;
return {
isHost: this.checkPermissionBit(playerPermissionNumber, 0),
};
}
subscribe = this.store.subscribe;
private getStoredSessionIds(): { sessionToken: string; userId: string } | null {
if (typeof window === "undefined") return null;
const sessionIds = localStorage.getItem("currentSessionIds");
if (!sessionIds) return null;
const sessionIdsJson = JSON.parse(sessionIds);
if (typeof sessionIdsJson.userId !== "string" || typeof sessionIdsJson.sessionToken !== "string") {
return null;
}
return { sessionToken: sessionIdsJson.sessionToken, userId: sessionIdsJson.userId };
}
private saveSessionIds(sessionToken: string, userId: string) {
if (typeof window !== "undefined") {
localStorage.setItem("currentSessionIds", JSON.stringify({ sessionToken, userId, joinCode: this.getState().joinCode }));
}
}
private saveJoinCode() {
const sessionIds = localStorage.getItem("currentSessionIds");
if (!sessionIds) return;
const sessionIdsJson = JSON.parse(sessionIds);
localStorage.setItem("currentSessionIds", JSON.stringify({ sessionToken: sessionIdsJson.sessionToken, userId: sessionIdsJson.userId, joinCode: this.getState().joinCode }));
}
private clearSessionIds() {
if (typeof window !== "undefined") {
const sessionIds = localStorage.getItem("currentSessionIds");
if (!sessionIds) return;
const sessionIdsJson = JSON.parse(sessionIds);
const lastSessionData = { joinCode: sessionIdsJson.joinCode };
localStorage.setItem("lastSessionIds", JSON.stringify(lastSessionData));
localStorage.removeItem("currentSessionIds");
}
}
isConnected(): boolean {
return this.socket?.connected ?? false;
}
hasRoomData(): boolean {
return get(this.store).gameState != -1;
}
getUserId(): string | undefined {
return this.getState().userId ?? undefined;
}
getUser(playerId?: string): PlayerObj | undefined {
if (!playerId) playerId = this.getUserId();
return this.getState().players.find((player) => player.PlayerId == playerId);
}
kickPlayer(playerId: string) {
if (!this.getPlayerPermissions().isHost) return;
this.socket?.emit("KickPlayer", JSON.stringify({ PlayerId: playerId }));
}
renamePlayer(playerId: string | undefined, newName: string) {
if (!playerId) playerId = this.getUserId();
if (!this.getPlayerPermissions().isHost && playerId != this.getUserId()) return;
this.socket?.emit("UpdatePlayer", JSON.stringify({ PlayerId: playerId, Username: newName }));
}
isCurrentPlayer(playerId: string): boolean {
return this.getState().userId == playerId;
}
connect(sessionToken?: string, userId?: string) {
if (!sessionToken) sessionToken = this.getState().sessionToken || undefined;
if (!userId) userId = this.getState().userId || undefined;
if (!sessionToken || !userId) {
const storedSessionIds = this.getStoredSessionIds();
if (!sessionToken) sessionToken = storedSessionIds?.sessionToken;
if (!userId) userId = storedSessionIds?.userId;
}
if (this.socket) {
console.warn(`Socket already connected! Rejecting new connection to ${sessionToken}`);
return;
}
this.socket = io({
transports: ["websocket"],
query: { sessionToken },
});
this.setupSocketEventHandlers(sessionToken, userId);
}
private setupSocketEventHandlers(sessionToken: string, userId: string) {
this.socket?.on("connect", () => this.handleConnect(sessionToken, userId));
this.socket?.on("disconnect", this.handleDisconnect.bind(this));
this.socket?.on("Status", this.handleStatus.bind(this));
this.socket?.on("RoomInfo", this.handleRoomInfo.bind(this));
this.socket?.on("error", this.handleError.bind(this));
}
private handleConnect(sessionToken: string, userId: string) {
console.info("Connected to room");
this.saveSessionIds(sessionToken, userId);
window.history.replaceState({}, "", "/Game");
this.store.update((state) => ({
...state,
socket: this.socket,
userId,
connected: true,
sessionToken,
}));
}
private handleDisconnect() {
console.info("Disconnected from server");
this.store.update((state) => ({ ...state, connected: false }));
}
private handleStatus(message: StatusInfoObj) {
console.log("Status: ", message);
if (message.IsError && message.StatusCode !== "connection_from_different_socket") {
this.leaveRoom();
}
if (message.IsError) {
this.socket = null;
window.history.replaceState({}, "", "/");
}
this.store.update((state) => ({
...state,
messages: [...state.messages, message],
}));
}
private handleRoomInfo(message: RoomInfoObj) {
console.log("RoomInfo: ", message);
this.store.update((state) => ({
...state,
roomId: message.RoomId,
joinCode: message.JoinCode,
gameState: message.GameState,
cardDeckId: message.CardDeckId,
players: message.Players,
}));
this.saveJoinCode();
this.store.update((state) => ({
...state,
messages: [...state.messages, message],
}));
}
private handleError(error: string) {
console.error("Socket error:", error);
}
sendMessage(message: string) {
if (this.socket && message.trim()) {
this.socket.emit("event", message);
}
}
leaveRoom() {
console.log("leave room");
if (this.socket) {
this.socket.disconnect();
this.socket = null;
}
if (this.getState().sessionToken) {
fetch(`/api/room/leave`, {
method: "POST",
body: JSON.stringify({
SessionToken: this.getState().sessionToken,
}),
headers: {
"Content-Type": "application/json",
},
});
}
this.clearSessionIds();
this.store.set({
roomId: null,
joinCode: null,
gameState: -1,
gameOptions: {},
players: [],
cardDeckId: null,
socket: null,
connected: false,
userId: null,
messages: [],
sessionToken: null,
});
window.history.replaceState({}, "", "/");
}
this.clearSessionIds();
this.store.set({
roomId: null,
joinCode: null,
gameState: -1,
gameOptions: {},
players: [],
cardDeckId: null,
socket: null,
connected: false,
userId: null,
messages: [],
sessionToken: null,
});
window.history.replaceState({}, "", "/");
}
}
export const sessionStore = new SessionManager();

View File

@ -1,6 +1,6 @@
import { writable } from 'svelte/store';
import { writable } from "svelte/store";
const getSystemTheme = () => window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
const getSystemTheme = () => (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
const storedTheme = localStorage.getItem("theme") as Theme | null;
const initialTheme: Theme = storedTheme === "dark" || storedTheme === "light" ? storedTheme : "system";
@ -10,7 +10,7 @@ export const theme = writable<Theme>(initialTheme);
const applyTheme = (value: Theme) => {
const resolvedTheme = value === "system" ? getSystemTheme() : value;
document.documentElement.classList.toggle("dark", resolvedTheme === "dark");
document.documentElement.setAttribute("data-theme", resolvedTheme);
document.body.classList.toggle("dark-theme", resolvedTheme === "dark");
@ -24,7 +24,7 @@ theme.subscribe(applyTheme);
// Watch for system theme changes when "system" mode is enabled
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
mediaQuery.addEventListener("change", () => {
theme.update(current => {
theme.update((current) => {
if (current === "system") applyTheme("system");
return current;
});
@ -35,7 +35,7 @@ export const setTheme = (value: Theme) => {
};
export const toggleTheme = () => {
theme.update(current => {
theme.update((current) => {
if (current === "dark") return "light";
if (current === "light") return "system";
return "dark";

View File

@ -1,7 +1,7 @@
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
export default {
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
// for more information about preprocessors
preprocess: vitePreprocess(),
}
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
// for more information about preprocessors
preprocess: vitePreprocess(),
};

View File

@ -1,21 +1,21 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"resolveJsonModule": true,
/**
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable checkJs if you'd like to use dynamic types in JS.
* Note that setting allowJs false does not prevent the use
* of JS in `.svelte` files.
*/
"allowJs": true,
"checkJs": true,
"isolatedModules": true,
"moduleDetection": "force"
},
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
"exclude": [".routify"]
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"resolveJsonModule": true,
/**
* Typecheck JS in `.svelte` and `.js` files by default.
* Disable checkJs if you'd like to use dynamic types in JS.
* Note that setting allowJs false does not prevent the use
* of JS in `.svelte` files.
*/
"allowJs": true,
"checkJs": true,
"isolatedModules": true,
"moduleDetection": "force"
},
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
"exclude": [".routify"]
}

View File

@ -1,7 +1,4 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
"files": [],
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
}

View File

@ -1,24 +1,24 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

View File

@ -1,26 +1,28 @@
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import routify from '@roxi/routify/vite-plugin'
import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import routify from "@roxi/routify/vite-plugin";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [
routify({/* config */ }),
tailwindcss(),
svelte()
],
server: {
host: true,
proxy: {
'/api': {
target: 'http://10.10.39.145:3000',
changeOrigin: true,
},
'/socket.io': {
target: 'http://10.10.39.145:3000',
ws: true,
changeOrigin: true,
}
}
}
})
plugins: [
routify({
/* config */
}),
tailwindcss(),
svelte(),
],
server: {
host: true,
proxy: {
"/api": {
target: "http://10.10.39.145:3000",
changeOrigin: true,
},
"/socket.io": {
target: "http://10.10.39.145:3000",
ws: true,
changeOrigin: true,
},
},
},
});