Aktualizacja do wersji 0.0.28 i poprawa formatowania raportów
- Zmieniono wersję z 0.0.27 na 0.0.28 w `package.json`, `dockerfile` i interfejsie użytkownika. - Dodano `useFormatNumber` i `useRedisKeyPrefix` do formatowania liczb oraz generowania prefixów do kluczy redis. - Zaktualizowano auto-importy ESLint i deklaracje typów dla nowych composables. - Poprawiono formatowanie raportu administracyjnego poprzez lepsze wiązanie danych i formatowanie wartości. - Dostosowano `AdministrationAccordion`, aby domyślnie rozwijał pierwszą sekcję. - Zmieniono komponenty wykresów i podpowiedzi na `useFormatNumber` dla spójnego formatowania. - Usprawniono obliczenia w `populationGrowth`, eliminując zbędne funkcje formatowania. - Zoptymalizowano klucze pamięci podręcznej dzięki `redisKeyPrefix` dla lepszej wydajności. - Zaktualizowano `.gitignore`, dodając katalog `auto-types`.
This commit is contained in:
@@ -508,6 +508,8 @@
|
|||||||
"PaginationNext": true,
|
"PaginationNext": true,
|
||||||
"PaginationPrev": true,
|
"PaginationPrev": true,
|
||||||
"useFetchPopulationReport": true,
|
"useFetchPopulationReport": true,
|
||||||
"useFetchAdministrationReport": true
|
"useFetchAdministrationReport": true,
|
||||||
|
"useRedisKeyPrefix": true,
|
||||||
|
"useFormatNumber": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -42,4 +42,6 @@ slim.report.json
|
|||||||
redis/data
|
redis/data
|
||||||
|
|
||||||
commit.txt
|
commit.txt
|
||||||
git-diff.txt
|
git-diff.txt
|
||||||
|
|
||||||
|
auto-types
|
||||||
@@ -14,7 +14,7 @@ RUN bun run build-only \
|
|||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
LABEL maintainer="garandplg@garandplg.com"
|
LABEL maintainer="garandplg@garandplg.com"
|
||||||
LABEL version="0.0.27"
|
LABEL version="0.0.28"
|
||||||
LABEL description="Garand's WG. Pocketbase + Redis + Bun + Vue3 + Vite + TypeScript + TailwindCSS + Shadcn-vue"
|
LABEL description="Garand's WG. Pocketbase + Redis + Bun + Vue3 + Vite + TypeScript + TailwindCSS + Shadcn-vue"
|
||||||
|
|
||||||
ARG PB_VERSION=0.22.26
|
ARG PB_VERSION=0.22.26
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "garands-world-game",
|
"name": "garands-world-game",
|
||||||
"version": "0.0.27",
|
"version": "0.0.28",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
4
src/auto-types/auto-imports.d.ts
vendored
4
src/auto-types/auto-imports.d.ts
vendored
@@ -340,6 +340,7 @@ declare global {
|
|||||||
const useFocus: typeof import('@vueuse/core')['useFocus']
|
const useFocus: typeof import('@vueuse/core')['useFocus']
|
||||||
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
|
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
|
||||||
const useFormField: typeof import('../components/ui/form/useFormField')['useFormField']
|
const useFormField: typeof import('../components/ui/form/useFormField')['useFormField']
|
||||||
|
const useFormatNumber: typeof import('../composables/useFormatNumber')['default']
|
||||||
const useFps: typeof import('@vueuse/core')['useFps']
|
const useFps: typeof import('@vueuse/core')['useFps']
|
||||||
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
|
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
|
||||||
const useGamepad: typeof import('@vueuse/core')['useGamepad']
|
const useGamepad: typeof import('@vueuse/core')['useGamepad']
|
||||||
@@ -394,6 +395,7 @@ declare global {
|
|||||||
const useProcessEndTurnCollectionsData: typeof import('../composables/useProcessEndTurnCollectionsData')['default']
|
const useProcessEndTurnCollectionsData: typeof import('../composables/useProcessEndTurnCollectionsData')['default']
|
||||||
const useRafFn: typeof import('@vueuse/core')['useRafFn']
|
const useRafFn: typeof import('@vueuse/core')['useRafFn']
|
||||||
const useRedis: typeof import('../composables/useRedis')['useRedis']
|
const useRedis: typeof import('../composables/useRedis')['useRedis']
|
||||||
|
const useRedisKeyPrefix: typeof import('../composables/useRedisKeyPrefix')['default']
|
||||||
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
|
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
|
||||||
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
|
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
|
||||||
const useRoute: typeof import('vue-router')['useRoute']
|
const useRoute: typeof import('vue-router')['useRoute']
|
||||||
@@ -822,6 +824,7 @@ declare module 'vue' {
|
|||||||
readonly useFocus: UnwrapRef<typeof import('@vueuse/core')['useFocus']>
|
readonly useFocus: UnwrapRef<typeof import('@vueuse/core')['useFocus']>
|
||||||
readonly useFocusWithin: UnwrapRef<typeof import('@vueuse/core')['useFocusWithin']>
|
readonly useFocusWithin: UnwrapRef<typeof import('@vueuse/core')['useFocusWithin']>
|
||||||
readonly useFormField: UnwrapRef<typeof import('../components/ui/form/useFormField')['useFormField']>
|
readonly useFormField: UnwrapRef<typeof import('../components/ui/form/useFormField')['useFormField']>
|
||||||
|
readonly useFormatNumber: UnwrapRef<typeof import('../composables/useFormatNumber')['default']>
|
||||||
readonly useFps: UnwrapRef<typeof import('@vueuse/core')['useFps']>
|
readonly useFps: UnwrapRef<typeof import('@vueuse/core')['useFps']>
|
||||||
readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']>
|
readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']>
|
||||||
readonly useGamepad: UnwrapRef<typeof import('@vueuse/core')['useGamepad']>
|
readonly useGamepad: UnwrapRef<typeof import('@vueuse/core')['useGamepad']>
|
||||||
@@ -876,6 +879,7 @@ declare module 'vue' {
|
|||||||
readonly useProcessEndTurnCollectionsData: UnwrapRef<typeof import('../composables/useProcessEndTurnCollectionsData')['default']>
|
readonly useProcessEndTurnCollectionsData: UnwrapRef<typeof import('../composables/useProcessEndTurnCollectionsData')['default']>
|
||||||
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
|
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
|
||||||
readonly useRedis: UnwrapRef<typeof import('../composables/useRedis')['useRedis']>
|
readonly useRedis: UnwrapRef<typeof import('../composables/useRedis')['useRedis']>
|
||||||
|
readonly useRedisKeyPrefix: UnwrapRef<typeof import('../composables/useRedisKeyPrefix')['default']>
|
||||||
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
|
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
|
||||||
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
|
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
|
||||||
readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
|
readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
|
||||||
|
|||||||
1
src/auto-types/components.d.ts
vendored
1
src/auto-types/components.d.ts
vendored
@@ -13,6 +13,7 @@ declare module 'vue' {
|
|||||||
AccordionTrigger: typeof import('./../components/ui/accordion/AccordionTrigger.vue')['default']
|
AccordionTrigger: typeof import('./../components/ui/accordion/AccordionTrigger.vue')['default']
|
||||||
AdministrationAccordion: typeof import('./../components/report/administration/administrationAccordion.vue')['default']
|
AdministrationAccordion: typeof import('./../components/report/administration/administrationAccordion.vue')['default']
|
||||||
AdministrationBurgCard: typeof import('./../components/report/administration/administrationBurgCard.vue')['default']
|
AdministrationBurgCard: typeof import('./../components/report/administration/administrationBurgCard.vue')['default']
|
||||||
|
AdministrationDetails: typeof import('./../components/report/administration/administrationDetails.vue')['default']
|
||||||
AdministrationProvincesCard: typeof import('./../components/report/administration/administrationProvincesCard.vue')['default']
|
AdministrationProvincesCard: typeof import('./../components/report/administration/administrationProvincesCard.vue')['default']
|
||||||
AdministrationReport: typeof import('./../components/report/administrationReport.vue')['default']
|
AdministrationReport: typeof import('./../components/report/administrationReport.vue')['default']
|
||||||
BuildingsReport: typeof import('./../components/report/buildingsReport.vue')['default']
|
BuildingsReport: typeof import('./../components/report/buildingsReport.vue')['default']
|
||||||
|
|||||||
@@ -85,11 +85,7 @@ const changePage = (page: number) => {
|
|||||||
class="mb-3 mt-6 h-[600px]"
|
class="mb-3 mt-6 h-[600px]"
|
||||||
:show-legend="false"
|
:show-legend="false"
|
||||||
:custom-tooltip="customChartTooltip"
|
:custom-tooltip="customChartTooltip"
|
||||||
:y-formatter="
|
:y-formatter="(tick, i) => useFormatNumber(tick)"
|
||||||
(tick, i) => {
|
|
||||||
return `${tick.toLocaleString('en-US')}`;
|
|
||||||
}
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ defineProps<{
|
|||||||
</span>
|
</span>
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ item.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="ml-4 font-semibold">{{ item.value.toLocaleString('en-US') }}</span>
|
<span class="ml-4 font-semibold">{{ useFormatNumber(item.value) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -16,12 +16,15 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const provinces = props.accordionItems.find(item => item.type === 'provinces')?.content ?? [];
|
const provinces = props.accordionItems.find(item => item.type === 'provinces')?.content ?? [];
|
||||||
const burgs = props.accordionItems.find(item => item.type === 'burgs')?.content ?? [];
|
const burgs = props.accordionItems.find(item => item.type === 'burgs')?.content ?? [];
|
||||||
|
|
||||||
const { cultureNames, religionNames } = await useFetchAdministrationReport(props.turn, props.state);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Accordion type="single" class="w-full" collapsible>
|
<Accordion
|
||||||
|
type="single"
|
||||||
|
class="w-full p-2"
|
||||||
|
collapsible
|
||||||
|
:default-value="props.accordionItems[0].title"
|
||||||
|
>
|
||||||
<AccordionItem v-for="item in props.accordionItems" :key="item.title" :value="item.title">
|
<AccordionItem v-for="item in props.accordionItems" :key="item.title" :value="item.title">
|
||||||
<AccordionTrigger class="items-center justify-center space-x-1">
|
<AccordionTrigger class="items-center justify-center space-x-1">
|
||||||
<h3 class="text-lg font-bold text-primary"> {{ item.title }} </h3>
|
<h3 class="text-lg font-bold text-primary"> {{ item.title }} </h3>
|
||||||
@@ -48,8 +51,8 @@ const { cultureNames, religionNames } = await useFetchAdministrationReport(props
|
|||||||
v-for="burg in burgs"
|
v-for="burg in burgs"
|
||||||
:key="burg.id"
|
:key="burg.id"
|
||||||
:burg="burg"
|
:burg="burg"
|
||||||
:cultures="cultureNames"
|
:turn="props.turn"
|
||||||
:religions="religionNames"
|
:state="props.state"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
@@ -63,6 +66,7 @@ const { cultureNames, religionNames } = await useFetchAdministrationReport(props
|
|||||||
:data="item.content"
|
:data="item.content"
|
||||||
type="donut"
|
type="donut"
|
||||||
:sort-function="(a, b) => b.amount - a.amount"
|
:sort-function="(a, b) => b.amount - a.amount"
|
||||||
|
:valueFormatter="value => `${useFormatNumber(value)}`"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { BurgsResponse, CulturesResponse, ReligionsResponse } from '@/types/pb-types';
|
import type { BurgsResponse, StatesResponse, TurnsResponse } from '@/types/pb-types';
|
||||||
import { Icon } from '@iconify/vue';
|
import { Icon } from '@iconify/vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
burg: BurgsResponse<unknown>;
|
burg: BurgsResponse<unknown>;
|
||||||
cultures: CulturesResponse<unknown>[];
|
turn: TurnsResponse<unknown>;
|
||||||
religions: ReligionsResponse<unknown>[];
|
state: StatesResponse<unknown, unknown, unknown, unknown, unknown>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const { cultureNames, religionNames } = await useFetchAdministrationReport(props.turn, props.state);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -25,20 +27,20 @@ const props = defineProps<{
|
|||||||
<div class="mr-3 mt-[-0.6rem] flex w-full flex-col">
|
<div class="mr-3 mt-[-0.6rem] flex w-full flex-col">
|
||||||
<p class="text-base">
|
<p class="text-base">
|
||||||
Populacja:
|
Populacja:
|
||||||
<span class="text-primary">{{ props.burg.population.toLocaleString('en-US') }}</span>
|
<span class="text-primary">{{ useFormatNumber(props.burg.population) }}</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="text-base">
|
<p class="text-base">
|
||||||
Kultura:
|
Kultura:
|
||||||
<span class="text-primary">
|
<span class="text-primary">
|
||||||
{{ props.cultures.find(culture => culture.id === props.burg.culture)?.name }}
|
{{ cultureNames.find(culture => culture.id === props.burg.culture)?.name }}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="text-base">
|
<p class="text-base">
|
||||||
Religia:
|
Religia:
|
||||||
<span class="text-primary">
|
<span class="text-primary">
|
||||||
{{ props.religions.find(religion => religion.id === props.burg.religion)?.name }}
|
{{ religionNames.find(religion => religion.id === props.burg.religion)?.name }}
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
157
src/components/report/administration/administrationDetails.vue
Normal file
157
src/components/report/administration/administrationDetails.vue
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { StatesResponse, TurnsResponse } from '@/types/pb-types';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
turn: TurnsResponse<unknown>;
|
||||||
|
state: StatesResponse<unknown, unknown, unknown, unknown, unknown>;
|
||||||
|
}>();
|
||||||
|
const { cultureNames, burgsData } = await useFetchAdministrationReport(props.turn, props.state);
|
||||||
|
|
||||||
|
const cells = props.state.cells;
|
||||||
|
const primaryCulture = cultureNames.find(
|
||||||
|
(cultureName: { id: string; name: string }) => cultureName.id === props.state.culture
|
||||||
|
).name;
|
||||||
|
const cultureCells = props.state.culturesCells as Record<string, number>;
|
||||||
|
|
||||||
|
const nonPrimaryCultureCells = Object.entries(cultureCells).reduce((suma, [klucz, wartość]) => {
|
||||||
|
return klucz === primaryCulture ? suma : suma + wartość;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
const burgs = burgsData.value.length;
|
||||||
|
|
||||||
|
const nonPrimaryCultureBurgs = burgsData.value.filter(
|
||||||
|
burg => burg.culture === primaryCulture
|
||||||
|
).length;
|
||||||
|
|
||||||
|
const sumGovernmentCapacityPoints = cells + nonPrimaryCultureCells + burgs + nonPrimaryCultureBurgs;
|
||||||
|
|
||||||
|
const progress = ref(33);
|
||||||
|
|
||||||
|
// TODO: Dodać limit administracyjny, wyliczanie % zapełnienia limitu i jego wypisywanie w <Progress />>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="w-full p-6">
|
||||||
|
<Label class="mt-3 text-lg" for="progress">
|
||||||
|
Wykorzystanie: 33 / 100 ( <span class="text-primary"> 33</span>% )
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
<Progress v-model="progress" class="mt-1 w-3/5" id="progress" />
|
||||||
|
|
||||||
|
<div class="mt-9 grid grid-cols-2 gap-10">
|
||||||
|
<div class="relative mt-2 h-auto w-full rounded-md border p-5">
|
||||||
|
<span class="absolute -top-4 left-2 bg-background px-2 text-xl text-primary">
|
||||||
|
Koszty administracyjne
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<Table class="mb-7">
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead> Typ </TableHead>
|
||||||
|
|
||||||
|
<TableHead> Punkty </TableHead>
|
||||||
|
|
||||||
|
<TableHead class="text-right"> Ilość </TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
|
||||||
|
<TableBody class="font-medium">
|
||||||
|
<TableRow>
|
||||||
|
<TableCell> Kratki </TableCell>
|
||||||
|
|
||||||
|
<TableCell> 1 </TableCell>
|
||||||
|
|
||||||
|
<TableCell class="text-right"> {{ useFormatNumber(cells) }} </TableCell>
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow>
|
||||||
|
<TableCell> Kratki ob. kultura </TableCell>
|
||||||
|
|
||||||
|
<TableCell> 1 </TableCell>
|
||||||
|
|
||||||
|
<TableCell class="text-right">
|
||||||
|
{{ useFormatNumber(nonPrimaryCultureCells) }}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow>
|
||||||
|
<TableCell> Miasta </TableCell>
|
||||||
|
|
||||||
|
<TableCell> 1 </TableCell>
|
||||||
|
|
||||||
|
<TableCell class="text-right"> {{ useFormatNumber(burgs) }} </TableCell>
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow>
|
||||||
|
<TableCell> Miasta ob. kultura </TableCell>
|
||||||
|
|
||||||
|
<TableCell> 1 </TableCell>
|
||||||
|
|
||||||
|
<TableCell class="text-right">
|
||||||
|
{{ useFormatNumber(nonPrimaryCultureBurgs) }}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
<p class="absolute bottom-3 start-1/3 mt-4 text-center text-lg">
|
||||||
|
Suma:
|
||||||
|
<span class="text-primary"> {{ useFormatNumber(sumGovernmentCapacityPoints) }} </span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative mt-2 h-auto w-full rounded-md border p-5">
|
||||||
|
<span class="absolute -top-4 left-2 bg-background px-2 text-xl text-primary">
|
||||||
|
Źródła pojemności
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<Table class="mb-7">
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead> Typ </TableHead>
|
||||||
|
|
||||||
|
<TableHead class="text-right"> Ilość </TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
|
||||||
|
<TableBody class="font-medium">
|
||||||
|
<TableRow>
|
||||||
|
<TableCell> Forma rządu </TableCell>
|
||||||
|
|
||||||
|
<TableCell class="text-right"> 0 </TableCell>
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow>
|
||||||
|
<TableCell> Technologia </TableCell>
|
||||||
|
|
||||||
|
<TableCell class="text-right"> 0 </TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
<p class="absolute bottom-3 start-1/3 mt-4 text-center text-lg">
|
||||||
|
Suma: <span class="text-primary"> 0 </span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
┌─── Pojemność Administracyjna ───────────────────────────────────────┐
|
||||||
|
│ │
|
||||||
|
│ Wykorzystanie: 387 / 500 ( 77% ) │
|
||||||
|
│ [█████████████████████░░░░░░░░░] │
|
||||||
|
│ │
|
||||||
|
│ ┌─ Koszty administracyjne ─┐ ┌─ Źródła pojemności ─┐ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ Kratki: 250 │ │ Forma rządu: 300 │ │
|
||||||
|
│ │ Kratki ob. kult: 50 │ │ Technologia: 200 │ │
|
||||||
|
│ │ Miasta: 75 │ │ │ │
|
||||||
|
│ │ Miasta ob. kult: 12 │ │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ Suma: 387 │ │ Suma: 500 │ │
|
||||||
|
│ └──────────────────────────┘ └──────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────────┘
|
||||||
|
-->
|
||||||
@@ -5,7 +5,7 @@ const props = defineProps<{ province: ProvincesResponse<unknown> }>();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex h-[165px] w-[500px] flex-col gap-2 rounded-md border">
|
<div class="flex h-[165px] w-[450px] flex-col gap-2 rounded-md border">
|
||||||
<div class="flex items-center justify-center">
|
<div class="flex items-center justify-center">
|
||||||
<span class="mr-2 h-3 w-3" v-if="props.province.color">
|
<span class="mr-2 h-3 w-3" v-if="props.province.color">
|
||||||
<svg width="100%" height="100%" viewBox="0 0 30 30">
|
<svg width="100%" height="100%" viewBox="0 0 30 30">
|
||||||
@@ -36,26 +36,22 @@ const props = defineProps<{ province: ProvincesResponse<unknown> }>();
|
|||||||
|
|
||||||
<p class="text-base">
|
<p class="text-base">
|
||||||
Populacja wiejska:
|
Populacja wiejska:
|
||||||
<span class="text-primary">{{
|
<span class="text-primary">{{ useFormatNumber(props.province.ruralPopulation) }}</span>
|
||||||
props.province.ruralPopulation.toLocaleString('en-US')
|
|
||||||
}}</span>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="text-base">
|
<p class="text-base">
|
||||||
Populacja miejska:
|
Populacja miejska:
|
||||||
<span class="text-primary">{{
|
<span class="text-primary">{{ useFormatNumber(props.province.urbanPopulation) }}</span>
|
||||||
props.province.urbanPopulation.toLocaleString('en-US')
|
|
||||||
}}</span>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="text-base">
|
<p class="text-base">
|
||||||
Ilość miast:
|
Ilość miast:
|
||||||
<span class="text-primary">{{ props.province.burgs.toLocaleString('en-US') }}</span>
|
<span class="text-primary">{{ useFormatNumber(props.province.burgs) }}</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="text-base">
|
<p class="text-base">
|
||||||
Ilość kratek:
|
Ilość kratek:
|
||||||
<span class="text-primary">{{ props.province.cells.toLocaleString('en-US') }}</span>
|
<span class="text-primary">{{ useFormatNumber(props.province.cells) }}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -68,14 +68,17 @@ function prepareChartData(content: object) {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="grid grid-cols-12 gap-3">
|
<div class="grid grid-cols-12 gap-3">
|
||||||
<div class="col-span-4 rounded-md border p-2">
|
<AdministrationAccordion
|
||||||
<AdministrationAccordion
|
class="col-span-6"
|
||||||
:accordionItems="accordionItems"
|
:accordionItems="accordionItems"
|
||||||
:turn="props.turn"
|
:turn="props.turn"
|
||||||
:state="props.state"
|
:state="props.state"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-span-8 rounded-md border p-2">Zawartość</div>
|
<AdministrationDetails
|
||||||
|
:state="props.state"
|
||||||
|
:turn="props.turn"
|
||||||
|
class="col-span-6 flex w-full flex-col items-center justify-center"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ const props = defineProps<{
|
|||||||
state: StatesResponse<unknown, unknown, unknown, unknown, unknown>;
|
state: StatesResponse<unknown, unknown, unknown, unknown, unknown>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { currentUser } = storeToRefs(listenCurrentUserStore());
|
const { redisKeyPrefix } = useRedisKeyPrefix(props.state.name, props.turn.value);
|
||||||
|
|
||||||
const flags: Flag[] = await useCachedData({
|
const flags: Flag[] = await useCachedData({
|
||||||
key: `${props.state.name}-${props.turn.value + 1}-${!['moderator', 'admin'].includes(currentUser.value?.role) ? currentUser.value?.id : 'Administration'} -- reportDiplomacyFlags`,
|
key: `${redisKeyPrefix} -- reportDiplomacyFlags`,
|
||||||
collection: 'states',
|
collection: 'states',
|
||||||
ttl: 1800,
|
ttl: 1800,
|
||||||
requestArgs: {
|
requestArgs: {
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ const totalData = computed(() => ({
|
|||||||
growth: ruralData.value.growth + urbanData.value.growth
|
growth: ruralData.value.growth + urbanData.value.growth
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const formatNumber = (num: number) => num.toLocaleString('en-US');
|
|
||||||
|
|
||||||
const getChangeColor = (change: number) => {
|
const getChangeColor = (change: number) => {
|
||||||
if (change > 0) return 'text-green-500';
|
if (change > 0) return 'text-green-500';
|
||||||
if (change < 0) return 'text-red-500';
|
if (change < 0) return 'text-red-500';
|
||||||
@@ -41,7 +39,7 @@ const getChangeSymbol = (change: number) => {
|
|||||||
|
|
||||||
const formatChange = (change: number) => {
|
const formatChange = (change: number) => {
|
||||||
const prefix = change > 0 ? '+' : '';
|
const prefix = change > 0 ? '+' : '';
|
||||||
return `${prefix}${formatNumber(change)}`;
|
return `${prefix}${useFormatNumber(change)}`;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -62,7 +60,7 @@ const formatChange = (change: number) => {
|
|||||||
|
|
||||||
<div class="numbers-display">
|
<div class="numbers-display">
|
||||||
<div class="text-2xl font-bold">
|
<div class="text-2xl font-bold">
|
||||||
{{ formatNumber(ruralData.current) }}
|
{{ useFormatNumber(ruralData.current) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :class="getChangeColor(ruralData.change)">
|
<div :class="getChangeColor(ruralData.change)">
|
||||||
@@ -71,7 +69,7 @@ const formatChange = (change: number) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-xl">
|
<div class="text-xl">
|
||||||
{{ formatNumber(ruralData.growth) }}
|
{{ useFormatNumber(ruralData.growth) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,7 +81,7 @@ const formatChange = (change: number) => {
|
|||||||
|
|
||||||
<div class="numbers-display">
|
<div class="numbers-display">
|
||||||
<div class="text-2xl font-bold">
|
<div class="text-2xl font-bold">
|
||||||
{{ formatNumber(urbanData.current) }}
|
{{ useFormatNumber(urbanData.current) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :class="getChangeColor(urbanData.change)">
|
<div :class="getChangeColor(urbanData.change)">
|
||||||
@@ -92,7 +90,7 @@ const formatChange = (change: number) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-xl">
|
<div class="text-xl">
|
||||||
{{ formatNumber(urbanData.growth) }}
|
{{ useFormatNumber(urbanData.growth) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -105,7 +103,7 @@ const formatChange = (change: number) => {
|
|||||||
|
|
||||||
<div class="flex items-center justify-center space-x-4">
|
<div class="flex items-center justify-center space-x-4">
|
||||||
<span class="text-2xl font-bold">
|
<span class="text-2xl font-bold">
|
||||||
{{ formatNumber(totalData.current) }}
|
{{ useFormatNumber(totalData.current) }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
@@ -116,7 +114,7 @@ const formatChange = (change: number) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="text-2xl">
|
<span class="text-2xl">
|
||||||
{{ formatNumber(totalData.growth) }}
|
{{ useFormatNumber(totalData.growth) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
3
src/composables/useFormatNumber.ts
Normal file
3
src/composables/useFormatNumber.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export default function useFormatNumber(num: number | Date) {
|
||||||
|
return num.toLocaleString('en-US');
|
||||||
|
}
|
||||||
11
src/composables/useRedisKeyPrefix.ts
Normal file
11
src/composables/useRedisKeyPrefix.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export default function useRedisKeyPrefix(state: string, turn: string) {
|
||||||
|
const { currentUser } = storeToRefs(listenCurrentUserStore());
|
||||||
|
|
||||||
|
const user = currentUser.value?.id ? `"${currentUser.value.id}"` : null;
|
||||||
|
|
||||||
|
const isUserNotAdmin = !['moderator', 'admin'].includes(currentUser.value?.role);
|
||||||
|
|
||||||
|
const redisKeyPrefix = `${state}-${turn + 1}-${isUserNotAdmin ? user : 'Administration'}`;
|
||||||
|
|
||||||
|
return { redisKeyPrefix };
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ useHead({
|
|||||||
Witaj na <span class="text-primary">Garandowym WG</span>!
|
Witaj na <span class="text-primary">Garandowym WG</span>!
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p class="mb-4 text-sm">Wersja: <span class="text-primary">0.0.27 Indev</span></p>
|
<p class="mb-4 text-sm">Wersja: <span class="text-primary">0.0.28 Indev</span></p>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://discord.gg/vhBmFVpR3w"
|
href="https://discord.gg/vhBmFVpR3w"
|
||||||
|
|||||||
@@ -33,14 +33,16 @@ const { currentUser } = storeToRefs(listenCurrentUserStore());
|
|||||||
const turn = computed<string>(() => (route.params as RouteParams).turn - 1);
|
const turn = computed<string>(() => (route.params as RouteParams).turn - 1);
|
||||||
const state = computed<string>(() => (route.params as RouteParams).state);
|
const state = computed<string>(() => (route.params as RouteParams).state);
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: `Garand's WG | Raport | Tura ${turn.value} | ${state.value}`
|
||||||
|
});
|
||||||
|
|
||||||
const user = computed<AuthModel | null>(() =>
|
const user = computed<AuthModel | null>(() =>
|
||||||
currentUser.value?.id ? `"${currentUser.value.id}"` : null
|
currentUser.value?.id ? `"${currentUser.value.id}"` : null
|
||||||
);
|
);
|
||||||
const isUserNotAdmin = !['moderator', 'admin'].includes(currentUser.value?.role);
|
const isUserNotAdmin = !['moderator', 'admin'].includes(currentUser.value?.role);
|
||||||
|
|
||||||
useHead({
|
const { redisKeyPrefix } = useRedisKeyPrefix(state.value, turn.value);
|
||||||
title: `Garand's WG | Raport | Tura ${turn.value} | ${state.value}`
|
|
||||||
});
|
|
||||||
|
|
||||||
const turnData = ref<TurnsResponse<unknown>>();
|
const turnData = ref<TurnsResponse<unknown>>();
|
||||||
const stateData = ref<StatesResponse<unknown, unknown, unknown, unknown, unknown>>();
|
const stateData = ref<StatesResponse<unknown, unknown, unknown, unknown, unknown>>();
|
||||||
@@ -49,7 +51,7 @@ const cultureData = ref<CulturesResponse<unknown>>();
|
|||||||
if (!user.value) router.push('/');
|
if (!user.value) router.push('/');
|
||||||
else {
|
else {
|
||||||
turnData.value = await useCachedData({
|
turnData.value = await useCachedData({
|
||||||
key: `${state.value}-${turn.value + 1} -- reportTurn`,
|
key: `${redisKeyPrefix} -- reportTurn`,
|
||||||
collection: 'turns',
|
collection: 'turns',
|
||||||
ttl: 1800,
|
ttl: 1800,
|
||||||
func: 'getFirstListItem',
|
func: 'getFirstListItem',
|
||||||
@@ -62,7 +64,7 @@ else {
|
|||||||
if (!turnData.value) throw new Error('Nie znaleziono tury');
|
if (!turnData.value) throw new Error('Nie znaleziono tury');
|
||||||
|
|
||||||
stateData.value = await useCachedData({
|
stateData.value = await useCachedData({
|
||||||
key: `${state.value}-${turn.value + 1}-${isUserNotAdmin ? user.value : 'Administration'} -- reportState`,
|
key: `${redisKeyPrefix} -- reportState`,
|
||||||
collection: 'states',
|
collection: 'states',
|
||||||
ttl: 1800,
|
ttl: 1800,
|
||||||
func: 'getFirstListItem',
|
func: 'getFirstListItem',
|
||||||
@@ -72,7 +74,7 @@ else {
|
|||||||
}).value,
|
}).value,
|
||||||
requestArgs: {
|
requestArgs: {
|
||||||
fields: [
|
fields: [
|
||||||
'id,name,nameFull,emblemSVG,color,culture,relations,biomesCells,culturesCells,religionsCells,capital,ruralPopulation,urbanPopulation'
|
'id,name,nameFull,emblemSVG,cells,color,culture,relations,biomesCells,culturesCells,religionsCells,capital,ruralPopulation,urbanPopulation'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -80,7 +82,7 @@ else {
|
|||||||
if (!stateData.value) throw new Error('Nie znaleziono kraju');
|
if (!stateData.value) throw new Error('Nie znaleziono kraju');
|
||||||
|
|
||||||
cultureData.value = await useCachedData({
|
cultureData.value = await useCachedData({
|
||||||
key: `${state.value}-${turn.value + 1}-${isUserNotAdmin ? user.value : 'Administration'} -- reportCultureTechnologyGroup`,
|
key: `${redisKeyPrefix} -- reportCultureTechnologyGroup`,
|
||||||
collection: 'cultures',
|
collection: 'cultures',
|
||||||
ttl: 1800,
|
ttl: 1800,
|
||||||
func: 'getFirstListItem',
|
func: 'getFirstListItem',
|
||||||
|
|||||||
Reference in New Issue
Block a user