From 75e34d9f757e7549fcbd11c21131e51d9fbd60b3 Mon Sep 17 00:00:00 2001 From: Spythere Date: Sat, 13 Apr 2024 19:26:52 +0200 Subject: [PATCH 01/19] chore(wiki): change table to grid layout - wip --- src/components/tabs/WikiListTab.vue | 101 ++++++++++++++++++++++++---- src/styles/global.scss | 2 - 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/src/components/tabs/WikiListTab.vue b/src/components/tabs/WikiListTab.vue index 55619e8..b03ac6f 100644 --- a/src/components/tabs/WikiListTab.vue +++ b/src/components/tabs/WikiListTab.vue @@ -24,12 +24,51 @@ + +
- + @@ -161,6 +200,12 @@ export default defineComponent({ methods: { isTractionUnit, + onItemSelect(vehicle: IVehicle) { + if (this.store.chosenVehicle?.type === vehicle.type) this.addVehicle(vehicle); + + this.previewVehicle(vehicle); + }, + mountObserver() { if (this.observer) return; @@ -168,23 +213,20 @@ export default defineComponent({ entries.forEach((entry) => { if (entry.intersectionRatio > 0) { entry.target - .querySelector('td:first-child > img')! - .setAttribute( - 'src', - entry.target.querySelector('td:first-child > img')!.getAttribute('data-src')! - ); + .querySelector('img')! + .setAttribute('src', entry.target.querySelector('img')!.getAttribute('data-src')!); } }); }); - (this.$refs['itemRefs'] as HTMLElement[]).forEach((el) => this.observer?.observe(el)); + (this.$refs['itemRefs'] as HTMLElement[])?.forEach((el) => this.observer?.observe(el)); }, toggleFilter(name: typeof this.currentFilterMode) { this.currentFilterMode = this.currentFilterMode == name ? 'all' : name; - const tableWrapperRef = this.$refs['table-wrapper'] as HTMLElement; + const vehiclesRef = this.$refs['vehicles'] as HTMLElement; - tableWrapperRef.scrollTo({ + vehiclesRef.scrollTo({ top: this.scrollTop, }); }, @@ -242,6 +284,13 @@ export default defineComponent({ computed: { computedTableData(): IWikiRow[] { return this.store.vehicleDataList + .filter( + (vehicle) => + new RegExp(`${this.searchedVehicleTypeName.trim()}`, 'i').test(vehicle.type) && + (this.currentFilterMode == 'all' || + (this.currentFilterMode == 'tractions' && isTractionUnit(vehicle)) || + (this.currentFilterMode == 'carriages' && !isTractionUnit(vehicle))) + ) .map((vehicle) => ({ vehicle, showImage: false, @@ -289,15 +338,43 @@ export default defineComponent({ } .actions-panel_search { + display: flex; + gap: 0.5em; + input { width: auto; } } -.tab_content { +.vehicles { display: grid; - grid-template-rows: 30px 770px; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 0.5em; + overflow: auto; + + max-height: 750px; + + margin-top: 0.75em; + padding: 0.25em; +} + +.vehicles > li { + display: flex; + gap: 0.5em; + + background-color: #161c2e; + padding: 0.5em; + + min-height: 75px; + cursor: pointer; +} + +.vehicles > li[data-preview='true'] { + background-color: #364165; +} + +.vehicles > li > img[data-team-only='true'] { + border: 3px solid green; } .table-wrapper { diff --git a/src/styles/global.scss b/src/styles/global.scss index 46b806f..0162a93 100644 --- a/src/styles/global.scss +++ b/src/styles/global.scss @@ -214,8 +214,6 @@ input[type='number'] { color: white; font-size: 1em; - width: 18em; - &:focus-visible { border-color: $accentColor; } From e72b73ccf086b4a3281075216482b0336dc8cdcf Mon Sep 17 00:00:00 2001 From: Spythere Date: Sun, 14 Apr 2024 00:09:52 +0200 Subject: [PATCH 02/19] fix: global styles fix --- src/components/tabs/StockGeneratorTab.vue | 30 ++++++++++++++++++++--- src/styles/global.scss | 3 ++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/components/tabs/StockGeneratorTab.vue b/src/components/tabs/StockGeneratorTab.vue index fe8c2ca..30aa139 100644 --- a/src/components/tabs/StockGeneratorTab.vue +++ b/src/components/tabs/StockGeneratorTab.vue @@ -12,19 +12,19 @@ {{ $t('stockgen.properties-desc') }} -
+
@@ -368,6 +368,28 @@ h2 { gap: 1em; } +.inputs { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(12em, 1fr)); + + flex-wrap: wrap; + gap: 0.5em; +} + +.inputs > label { + display: flex; + flex-direction: column; + gap: 0.25em; + + span { + color: #ccc; + } + + input[type='text'] { + background-color: white; + } +} + .generator_options { display: flex; flex-direction: column; diff --git a/src/styles/global.scss b/src/styles/global.scss index 0162a93..d0db630 100644 --- a/src/styles/global.scss +++ b/src/styles/global.scss @@ -7,7 +7,7 @@ $secondaryColor: #1b1b1b; $accentColor: #e4c428; $sponsorColor: salmon; -$teamColor: gold; +$teamColor: #ff4848; @font-face { font-family: 'Lato'; @@ -210,6 +210,7 @@ input[type='number'] { outline: none; padding: 0.25em 0.35em; + height: 100%; color: white; font-size: 1em; From 99cbde382834f37b9a7b5b0535c2433640027e60 Mon Sep 17 00:00:00 2001 From: Spythere Date: Sun, 14 Apr 2024 00:12:47 +0200 Subject: [PATCH 03/19] chore: config port change --- vite.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vite.config.ts b/vite.config.ts index f4ec503..e2f87a8 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -6,7 +6,7 @@ import { VitePWA } from 'vite-plugin-pwa'; // https://vitejs.dev/config/ export default defineConfig({ server: { - port: 2137, + port: 2138, }, plugins: [ vue(), From baa39a5a996b55f7ad48b348290574fd5a88860d Mon Sep 17 00:00:00 2001 From: Spythere Date: Sun, 14 Apr 2024 00:13:01 +0200 Subject: [PATCH 04/19] chore: wiki list tab revamp --- src/components/sections/TrainImageSection.vue | 25 +- src/components/tabs/WikiListTab.vue | 394 +++++------------- src/locales/en.json | 25 +- src/locales/pl.json | 25 +- 4 files changed, 138 insertions(+), 331 deletions(-) diff --git a/src/components/sections/TrainImageSection.vue b/src/components/sections/TrainImageSection.vue index 086a61c..2fa738c 100644 --- a/src/components/sections/TrainImageSection.vue +++ b/src/components/sections/TrainImageSection.vue @@ -44,7 +44,7 @@ }}
- {{ + - {{ + {{ $t('preview.team-only') }} @@ -157,22 +157,13 @@ img { } } -// .train-image { -// &__content { -// &.sponsor img { -// border: 1px solid salmon; -// } +.sponsor-only { + color: $sponsorColor; +} -// img { -// max-width: 380px; -// width: 100%; -// height: 100%; -// border: 1px solid white; - -// cursor: zoom-in; -// } -// } -// } +.team-only { + color: $teamColor; +} .image-info { font-size: 1.1em; diff --git a/src/components/tabs/WikiListTab.vue b/src/components/tabs/WikiListTab.vue index b03ac6f..033abdb 100644 --- a/src/components/tabs/WikiListTab.vue +++ b/src/components/tabs/WikiListTab.vue @@ -5,116 +5,65 @@
-
-
- - -
- - + + +
  • - + {{ vehicle.type.replace(/_/g, ' ') }}
    {{ $t(`wiki.${vehicle.group}`) }} | {{ isTractionUnit(vehicle) ? vehicle.cabinType : vehicle.constructionType }}
    - {{ vehicle.maxSpeed }}km/h | {{ (vehicle.weight / 1000).toFixed(1) }}t | - {{ vehicle.length }}m + {{ vehicle.length }}m | {{ (vehicle.weight / 1000).toFixed(1) }}t | + {{ vehicle.maxSpeed }}km/h
- -
- -
@@ -128,40 +77,13 @@ import { isTractionUnit } from '../../utils/vehicleUtils'; import stockMixin from '../../mixins/stockMixin'; import imageMixin from '../../mixins/imageMixin'; -type SorterID = - | 'type' - | 'constructionType' - | 'image' - | 'length' - | 'weight' - | 'maxSpeed' - | 'cargoCount' - | 'group' - | 'coldStart'; +const sorters = ['type', 'group', 'length', 'weight', 'maxSpeed'] as const; +const filters = ['vehicles-all', 'vehicles-traction', 'vehicles-wagon'] as const; -interface IWikiHeader { - id: SorterID; - sortable: boolean; - for: 'all' | 'carriages' | 'tractions'; -} +type SorterType = (typeof sorters)[number]; +type SorterDirection = 'asc' | 'desc'; -interface IWikiRow { - vehicle: IVehicle; - show: boolean; - showImage: boolean; -} - -const headers: IWikiHeader[] = [ - { id: 'image', sortable: false, for: 'all' }, - { id: 'type', sortable: true, for: 'all' }, - { id: 'group', sortable: true, for: 'all' }, - { id: 'constructionType', sortable: true, for: 'all' }, - { id: 'length', sortable: true, for: 'all' }, - { id: 'weight', sortable: true, for: 'all' }, - { id: 'maxSpeed', sortable: true, for: 'all' }, - // { id: 'coldStart', sortable: true, for: 'tractions' }, - // { id: 'cargoCount', sortable: true, for: 'carriages' }, -]; +type FilterType = (typeof filters)[number]; export default defineComponent({ mixins: [stockPreviewMixin, stockMixin, imageMixin], @@ -170,31 +92,27 @@ export default defineComponent({ return { store: useStore(), observer: null as IntersectionObserver | null, - headers, - scrollTop: 0, + sorters: sorters, + filters: filters, searchedVehicleTypeName: '', - currentSorter: { - id: 'type' as SorterID, - direction: 1, - }, + sorterType: 'type' as SorterType, + sorterDirection: 'asc' as SorterDirection, - currentFilterMode: 'all' as 'all' | 'tractions' | 'carriages', + filterType: 'vehicles-all' as FilterType, }; }, - mounted() { - this.mountObserver(); - }, + watch: { + computedVehicles() { + const vehiclesRef = this.$refs['vehicles'] as HTMLElement; - activated() { - const tableWrapperRef = this.$refs['table-wrapper'] as HTMLElement; - - tableWrapperRef.scrollTo({ - top: this.scrollTop, - }); + vehiclesRef.scrollTo({ + top: 0, + }); + }, }, methods: { @@ -206,115 +124,59 @@ export default defineComponent({ this.previewVehicle(vehicle); }, - mountObserver() { - if (this.observer) return; + sortVehicles(v1: IVehicle, v2: IVehicle) { + const direction = this.sorterDirection == 'asc' ? 1 : -1; - this.observer = new IntersectionObserver((entries) => { - entries.forEach((entry) => { - if (entry.intersectionRatio > 0) { - entry.target - .querySelector('img')! - .setAttribute('src', entry.target.querySelector('img')!.getAttribute('data-src')!); - } - }); - }); - - (this.$refs['itemRefs'] as HTMLElement[])?.forEach((el) => this.observer?.observe(el)); - }, - - toggleFilter(name: typeof this.currentFilterMode) { - this.currentFilterMode = this.currentFilterMode == name ? 'all' : name; - const vehiclesRef = this.$refs['vehicles'] as HTMLElement; - - vehiclesRef.scrollTo({ - top: this.scrollTop, - }); - }, - - toggleSorter(header: IWikiHeader) { - if (!header.sortable) return; - - if (header.id == this.currentSorter.id) this.currentSorter.direction *= -1; - this.currentSorter.id = header.id; - }, - - sortTableRows(row1: IWikiRow, row2: IWikiRow) { - if (!row1.show) return 0; - - const { id, direction } = this.currentSorter; - - switch (id) { + switch (this.sorterType) { case 'type': - case 'constructionType': case 'group': - return direction == 1 - ? row1.vehicle[id].localeCompare(row2.vehicle[id]) - : row2.vehicle[id].localeCompare(row1.vehicle[id]); + return direction * v1[this.sorterType].localeCompare(v2[this.sorterType]); case 'weight': case 'length': case 'maxSpeed': - return Math.sign(row1.vehicle[id] - row2.vehicle[id]) * direction; + return Math.sign(v1[this.sorterType] - v2[this.sorterType]) * direction; - case 'cargoCount': - return ( - Math.sign( - (!isTractionUnit(row1.vehicle) ? row1.vehicle.cargoTypes.length || -1 : -1) - - (!isTractionUnit(row2.vehicle) ? row2.vehicle.cargoTypes.length || -1 : -1) - ) * direction - ); + // case 'cargoCount': + // return ( + // Math.sign( + // (!isTractionUnit(v1) ? v1.cargoTypes.length || -1 : -1) - + // (!isTractionUnit(row2.vehicle) ? row2.vehicle.cargoTypes.length || -1 : -1) + // ) * direction + // ); - case 'coldStart': - return ( - ((isTractionUnit(row1.vehicle) && row1.vehicle.coldStart ? 1 : -1) - - (isTractionUnit(row2.vehicle) && row2.vehicle.coldStart ? 1 : -1)) * - direction - ); + // case 'coldStart': + // return ( + // ((isTractionUnit(v1) && v1.coldStart ? 1 : -1) - + // (isTractionUnit(row2.vehicle) && row2.vehicle.coldStart ? 1 : -1)) * + // direction + // ); default: - break; + return v1.type.localeCompare(v2.type) * direction; } - - return direction == 1 - ? row1.vehicle.type.localeCompare(row2.vehicle.type) - : row2.vehicle.type.localeCompare(row1.vehicle.type); }, }, computed: { - computedTableData(): IWikiRow[] { + computedVehicles() { return this.store.vehicleDataList .filter( (vehicle) => new RegExp(`${this.searchedVehicleTypeName.trim()}`, 'i').test(vehicle.type) && - (this.currentFilterMode == 'all' || - (this.currentFilterMode == 'tractions' && isTractionUnit(vehicle)) || - (this.currentFilterMode == 'carriages' && !isTractionUnit(vehicle))) + (this.filterType == 'vehicles-all' || + (this.filterType == 'vehicles-traction' && isTractionUnit(vehicle)) || + (this.filterType == 'vehicles-wagon' && !isTractionUnit(vehicle))) ) - .map((vehicle) => ({ - vehicle, - showImage: false, - show: - new RegExp(`${this.searchedVehicleTypeName.trim()}`, 'i').test(vehicle.type) && - (this.currentFilterMode == 'all' || - (this.currentFilterMode == 'tractions' && isTractionUnit(vehicle)) || - (this.currentFilterMode == 'carriages' && !isTractionUnit(vehicle))), - })) - .sort((a, b) => this.sortTableRows(a, b)); - }, - - visibleHeaders() { - const filtersActive = this.currentFilterMode; - - return this.headers.filter((header) => header.for == 'all' || header.for == filtersActive); + .sort((v1, v2) => this.sortVehicles(v1, v2)); }, areTractionVehiclesShown() { - return this.currentFilterMode == 'all' || this.currentFilterMode == 'tractions'; + return this.filterType == 'vehicles-all' || this.filterType == 'vehicles-traction'; }, areCarriagesShown() { - return this.currentFilterMode == 'all' || this.currentFilterMode == 'carriages'; + return this.filterType == 'vehicles-all' || this.filterType == 'vehicles-wagon'; }, }, }); @@ -323,26 +185,21 @@ export default defineComponent({ diff --git a/src/components/sections/InputsSection.vue b/src/components/sections/InputsSection.vue index a7728d7..5d7d6b8 100644 --- a/src/components/sections/InputsSection.vue +++ b/src/components/sections/InputsSection.vue @@ -28,7 +28,8 @@ {{ $t('inputs.input-vehicle') }} @@ -59,7 +60,8 @@ @@ -84,6 +86,7 @@ +