refactor: new order structure, added new order instructions (wip)

This commit is contained in:
2025-09-24 02:31:59 +02:00
parent 35a883d608
commit 7afef587cc
16 changed files with 877 additions and 107 deletions
+13 -22
View File
@@ -1,47 +1,38 @@
<template> <template>
<div id="app_wrapper"> <div id="app_wrapper">
<UpdateCard />
<router-view />
<transition name="slide-anim"> <transition name="slide-anim">
<div v-if="needRefresh" class="update-prompt" @click="updateServiceWorker(true)"> <UpdateCard />
{{ $t('update.update-available-text') }}
<u>{{ $t('update.update-available-underline') }}</u>
</div>
</transition> </transition>
<footer> <RouterView />
&copy; <a href="https://td2.info.pl/profile/?u=20777">Spythere</a>
{{ new Date().getUTCFullYear() }} | <transition name="slide-anim">
<button class="g-button text" @click="store.updateCardOpen = true">v{{ appVersion }}</button> <UpdatePrompt />
</footer> </transition>
<AppFooter :version="appVersion" />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { useRegisterSW } from 'virtual:pwa-register/vue'; import UpdateCard from './components/Global/UpdateCard.vue';
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import packageInfo from '../package.json'; import packageInfo from '../package.json';
import { useStore } from './store/store'; import { useStore } from './store/store';
import orderStorageMixin from './mixins/orderStorageMixin'; import orderStorageMixin from './mixins/orderStorageMixin';
import StorageManager from './managers/storageManager'; import StorageManager from './managers/storageManager';
import axios from 'axios'; import axios from 'axios';
import UpdateCard from './components/UpdateCard.vue'; import UpdatePrompt from './components/Global/UpdatePrompt.vue';
import AppFooter from './components/App/AppFooter.vue';
const STORAGE_VERSION_KEY = 'app_version'; const STORAGE_VERSION_KEY = 'app_version';
export default defineComponent({ export default defineComponent({
components: { UpdateCard }, components: { UpdateCard, UpdatePrompt, AppFooter },
mixins: [orderStorageMixin], mixins: [orderStorageMixin],
setup() {
const { offlineReady, needRefresh, updateServiceWorker } = useRegisterSW({ immediate: true });
return { offlineReady, needRefresh, updateServiceWorker };
},
data() { data() {
return { appVersion: packageInfo.version, store: useStore() }; return { appVersion: packageInfo.version, store: useStore() };
}, },
+22
View File
@@ -0,0 +1,22 @@
<template>
<footer>
&copy; <a href="https://td2.info.pl/profile/?u=20777">Spythere</a>
{{ new Date().getUTCFullYear() }} |
<button class="g-button text" @click="store.updateCardOpen = true">v{{ props.version }}</button>
</footer>
</template>
<script setup lang="ts">
import { useStore } from '../../store/store';
const store = useStore();
const props = defineProps({
version: {
type: String,
required: true
}
});
</script>
<style scoped></style>
+7
View File
@@ -0,0 +1,7 @@
<template>
<div></div>
</template>
<script setup lang="ts"></script>
<style scoped></style>
@@ -23,7 +23,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { Converter } from 'showdown'; import { Converter } from 'showdown';
import { useStore } from '../store/store'; import { useStore } from '../../store/store';
const converter = new Converter(); const converter = new Converter();
const store = useStore(); const store = useStore();
+14
View File
@@ -0,0 +1,14 @@
<template>
<div v-if="needRefresh" class="update-prompt" @click="updateServiceWorker(true)">
{{ $t('update.update-available-text') }}
<u>{{ $t('update.update-available-underline') }}</u>
</div>
</template>
<script setup lang="ts">
import { useRegisterSW } from 'virtual:pwa-register/vue';
const { offlineReady, needRefresh, updateServiceWorker } = useRegisterSW({ immediate: true });
</script>
<style scoped></style>
+1 -1
View File
@@ -38,7 +38,7 @@ export default defineComponent({
}); });
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
@use '../styles/colors'; @use '../styles/colors';
$darkModeTextCol: #eee; $darkModeTextCol: #eee;
+20
View File
@@ -0,0 +1,20 @@
<template>
<div class="order" :class="{ dark: store.orderDarkMode }">
<OrderHeader />
<OrderMainContent />
<OrderFooter />
</div>
</template>
<script setup lang="ts">
import { useStore } from '../../store/store';
import OrderHeader from './OrderHeader.vue';
import OrderMainContent from './OrderMainContent.vue';
import OrderFooter from './OrderFooter.vue';
const store = useStore();
</script>
<style lang="scss">
@use '../../styles/order';
</style>
+7
View File
@@ -0,0 +1,7 @@
<template>
<div></div>
</template>
<script setup lang="ts"></script>
<style scoped></style>
+85
View File
@@ -0,0 +1,85 @@
<template>
<table class="order-table">
<tbody>
<tr>
<td style="padding: 0.25em"><b>Rozkaz pisemny</b></td>
</tr>
<tr>
<td width="50%">
<div class="header-input-box">
<input
type="text"
class="order-input"
id="header-A"
v-model="store.orderData.header.A"
/>
<label class="order-input-label" for="header-A">{{ t('order.header.A') }}</label>
</div>
</td>
<td>
<div class="header-input-box">
<input
type="date"
class="order-input"
id="header-B"
v-model="store.orderData.header.B"
/>
<label class="order-input-label" for="header-B">{{ t('order.header.B') }}</label>
</div>
</td>
</tr>
<tr>
<td>
<div class="header-input-box">
<input
type="text"
class="order-input"
id="header-C"
v-model="store.orderData.header.C"
/>
<label class="order-input-label" for="header-C">{{ t('order.header.C') }}</label>
</div>
</td>
<td>
<div class="header-input-box">
<input
type="text"
class="order-input"
id="header-D"
v-model="store.orderData.header.D"
/>
<label class="order-input-label" for="header-D">{{ t('order.header.D') }}</label>
</div>
</td>
</tr>
</tbody>
</table>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { useStore } from '../../store/store';
const { t } = useI18n();
const store = useStore();
</script>
<style scoped>
.header-input-box {
width: 100%;
padding: 0 1rem;
}
.order-input {
max-width: 100%;
width: 100%;
text-align: left;
}
.order-table,
.order-table tr:last-child td {
border-bottom: none;
}
</style>
+212
View File
@@ -0,0 +1,212 @@
<template>
<table class="order-table">
<tbody>
<tr>
<td width="10%" class="order-instruction-number">
<label class="order-instruction-checkbox">
<input type="checkbox" v-model="store.orderData.instructions[0].active" />
<div class="checkmark"></div>
<div class="text">22</div>
</label>
</td>
<td>
<b>
{{ t('order.22.text') }}
</b>
</td>
<td width="5%" class="order-instruction-number">
<label class="order-instruction-checkbox">
<input type="checkbox" v-model="store.orderData.instructions[1].active" />
<div class="checkmark"></div>
<div class="text">99</div>
</label>
</td>
<td width="45%">
<div>
<b>{{ t('order.99.text') }}</b>
</div>
<input
type="text"
class="order-input"
id="input-99-x1"
v-model="store.orderData.instructions[1].inputFields!.x1"
/>
<label for="input-99-x1" class="order-input-label">{{ t('order.99.x1') }}</label>
</td>
</tr>
<!-- From 21.10 -->
<tr v-for="(instruction, i) in store.orderData.instructions.slice(2)">
<td width="10%" class="order-instruction-number">
<label class="order-instruction-checkbox">
<input type="checkbox" v-model="instruction.active" />
<div class="checkmark"></div>
<div class="text">{{ instruction.name }}</div>
</label>
</td>
<td colspan="3">
<i18n-t :keypath="`order.${instruction.key}.text`" tag="div">
<template v-slot:bold1>
<b>{{ t(`order.${instruction.key}.bold1`) }}</b>
</template>
<template v-slot:bold2>
<b>{{ t(`order.${instruction.key}.bold2`) }}</b>
</template>
<template v-slot:underline1>
<u>{{ t(`order.${instruction.key}.underline1`) }}</u>
</template>
<template v-slot:highlight1>
<u>
<b>{{ t(`order.${instruction.key}.highlight1`) }}</b>
</u>
</template>
<template v-slot:highlight2>
<u>
<b>{{ t(`order.${instruction.key}.highlight2`) }}</b>
</u>
</template>
<template v-slot:br>
<br />
</template>
<template v-slot:[fieldKey] v-for="(_, fieldKey) in instruction.inputFields">
<input
class="order-input"
:id="`order-${instruction.key}-${fieldKey}`"
:style="{ width: calculateInputWidthByFieldName(fieldKey) }"
v-model="instruction.inputFields[fieldKey]"
:placeholder="t(`order.${instruction.key}.${fieldKey}`)"
/>
</template>
<template v-for="(selectField, fieldKey) in instruction.selectFields" v-slot:[fieldKey]>
<select
class="order-select"
:id="`order-${instruction.key}-${fieldKey}`"
v-model="instruction.inputFields[fieldKey]"
>
<option :value="value" v-for="value in selectField.options">
{{ t(`order.${instruction.key}.${value}`) }}
</option>
</select>
<!-- <input
class="order-input"
:id="`order-${instruction.key}-${fieldKey}`"
v-model="instruction.optionFields[fieldKey]"
:placeholder="t(`order.${instruction.key}.${fieldKey}`)"
/> -->
</template>
</i18n-t>
</td>
</tr>
</tbody>
</table>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { useStore } from '../../store/store';
import { onMounted, watch } from 'vue';
const { t } = useI18n();
const store = useStore();
onMounted(() => {
generateMessage();
});
watch(
store.orderData,
() => {
generateMessage();
},
{ deep: true }
);
function calculateInputWidthByFieldName(fieldName: string) {
if (fieldName.startsWith('track')) return '90px';
else if (fieldName.startsWith('signalbox')) return '150px';
else if (fieldName.startsWith('signal')) return '150px';
return '100px';
}
function generateMessage() {
let messageHtml = `<b>${t('order.title')}</b><br />`;
messageHtml += '-------------<br />';
const headerData = store.orderData['header'];
Object.entries(headerData).forEach(([key, value]) => {
messageHtml += `${t('order.header.' + key)}: ${value}<br />`;
});
messageHtml += '-------------<br />';
const instructions = store.orderData['instructions'];
Object.entries(instructions).forEach(([i, value]) => {
if (value.active) {
if (value.inputFields) {
const localeKey = `order.${value.key}`;
const messageValues = Object.values(value.inputFields).map((fieldKey: string) => {
if (fieldKey.startsWith('select')) return t(`order.${value.key}.${fieldKey}`);
return fieldKey || '---';
});
messageHtml += `<b>[${value.name}]</b> ${t(
localeKey + '.message-html',
messageValues
)}<br />`;
} else {
messageHtml += `<b>[${i}]</b> ${t('order.' + i + '.message-html')}<br />`;
}
}
});
store.orderMessage = messageHtml;
}
</script>
<style lang="scss" scoped>
.order-table {
border-top: none;
border-bottom: none;
td {
padding: 0.25em;
}
tr:not(:first-child) td {
padding: 0.25em 1em;
line-height: 2em;
text-align: justify;
}
}
.order-instruction-number {
position: relative;
height: 65px;
& > label {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding: 0.5em;
}
}
</style>
-69
View File
@@ -1,69 +0,0 @@
<template>
<div class="order-helper g-modal">
<div class="modal-bg" @click="store.helperModalOpen = false"></div>
<div class="content modal-content">
<h2>Rozkazy pisemne - najczęstsze przypadki zastosowań w TD2</h2>
<hr />
<ul>
<li>
<b>Przetaczanie (manewr) taboru poza wskaźnik W 5 (granicy przetaczania)</b>
<p>
Rozkazu <u>nie stosujemy</u> w przypadku wyjazdu taboru na szlak dwutorowy, na którym
odbywa się ruch w kierunku zasadniczym, tj. "prawostronnym". Dla wszystkich szlaków
jednotorowych lub dwutorowych w sytuacji innej niż wymieniona wykorzystujemy działkę 4.
rozkazu pisemnego "S". <br /><br />
<i
>Szczegółowe informacje: instrukcja Ir-1 (R-1) § 12 pkt 4 "Manewry na torach
głównych"</i
>
</p>
<button class="g-button action">Wygeneruj treść rozkazu</button>
</li>
</ul>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { useStore } from '../store/store';
import orderHelperData from '../data/orderHelperData.json';
export default defineComponent({
setup() {
return { store: useStore(), orderHelperData };
}
});
</script>
<style lang="scss" scoped>
@use '../styles/colors';
.content {
width: 100%;
max-width: 800px;
height: 100vh;
max-height: 800px;
margin: 1em;
padding: 1em;
background-color: #2b2b2b;
}
h2 {
text-align: center;
}
ul {
text-align: left;
li b {
font-size: 1.1em;
color: colors.$accentCol;
}
}
</style>
-3
View File
@@ -1,3 +0,0 @@
{
"orderS": ["D"]
}
+171
View File
@@ -68,5 +68,176 @@
"title": "Aktywne RJ i gracze na scenerii", "title": "Aktywne RJ i gracze na scenerii",
"subtitle": "Kliknij na gracza, aby wypełnić obecny rozkaz jego danymi", "subtitle": "Kliknij na gracza, aby wypełnić obecny rozkaz jego danymi",
"no-trains": "Brak pociągów do wyświetlenia" "no-trains": "Brak pociągów do wyświetlenia"
},
"order": {
"title": "Rozkaz pisemny",
"header": {
"A": "A Nr pociągu {'|'} składu manewrowego",
"B": "B Data",
"C": "C Lokalizacja pociągu {'|'} składu manewrowego",
"D": "D Lokalizacja nadawcy"
},
"22": {
"text": "Dotyczy jazdy torem lewym",
"message-html": "<b>Dotyczy jazdy torem lewym</b>"
},
"99": {
"text": "Odwołanie rozkazu pisemnego",
"x1": "x.1 Identyfikator rozkazu pisemnego",
"message-html": "<b>Odwołanie rozkazu pisemnego</b> {0}"
},
"2110": {
"text": "{bold1} z toru nr {track1} z {signalbox1} {br} na tor nr {track2} w kierunku {signalbox2} {br} Pominięcie sygnałów stój {signal1} i {signal2} i {signal3}",
"bold1": "Zezwalam na wyjazd",
"track1": "x.1 tor",
"signalbox1": "x.2 posterunek",
"track2": "x.3 tor",
"signalbox2": "x.4 posterunek",
"signal1": "x.5 sygnalizator",
"signal2": "x.6 sygnalizator",
"signal3": "x.7 sygnalizator",
"message-html": "<b>Zezwalam na wyjazd</b> z toru nr {0} z {1} na tor nr {2} w kierunku {3}. <br /> Pominięcie sygnałów stój {4} i {5} i {6}"
},
"2115": {
"text": "{bold1} z toru nr {track1} do {signalbox1} na tor nr {track2} {br} Pominięcie sygnałów {signal1} i {signal2} i {signal3}",
"bold1": "Zezwalam na wjazd",
"track1": "x.1 tor",
"signalbox1": "x.2 posterunek",
"track2": "x.3 tor",
"signal1": "x.4 sygnalizator",
"signal2": "x.5 sygnalizator",
"signal3": "x.6 sygnalizator",
"message-html": "<b>Zezwalam na wjazd</b> z toru nr {0} do {1} na tor nr {2} <br /> Pominięcie sygnałów {3} i {4} i {5}"
},
"2120": {
"text": "Od {signalbox1} do {signalbox2} po torze {track1} {br} {highlight1} {br} {underline1}{highlight2}.",
"highlight1": "wskazania semaforów SBL są nieważne.",
"underline1": "Zachować ostrożność od semafora ze wskaźnikiem",
"highlight2": " W18",
"signalbox1": "x.1 posterunek",
"signalbox2": "x.2 posterunek",
"track1": "x.3 nr toru",
"message-html": "Od {0} do {1} po torze {2} <u><b>wskazania semaforów SBL są nieważne.</b> Zachować ostrożność od semafora ze wskaźnikiem<b>W18.</b></u>"
},
"2125": {
"text": "Zezwalam przejechać za {select1} w kierunku {signalbox1} torem {track1} do km {km1} do godz. {hour1}.",
"select1-a": "wskaźnik W5",
"select1-b": "ostatni rozjazd",
"signalbox1": "x.1 posterunek",
"track1": "x.2 tor",
"km1": "x.3 km",
"hour1": "x.4 godzina",
"message-html": "Zezwalam przejechać za {0} w kierunku {1} torem {2} do km {3} do godz. {4}."
},
"2135": {
"text": "{bold1} po torze nr {track1} w kierunku {signalbox1}.",
"bold1": "Zezwalam na kontynuacje jazdy",
"track1": "x.1 tor",
"signalbox1": "x.2 posterunek",
"message-html": "<b>Zezwalam na kontynuacje jazdy</b> po torze {0} w kierunku {1}"
},
"2140": {
"text": "{bold1} na posterunku/szlaku {signalbox1}{'|'}{signalbox2} w km {km1} celem {other1}",
"bold1": "Zatrzymanie pociągu",
"signalbox1": "x.1 posterunek",
"signalbox2": "x.2 posterunek",
"km1": "x.3 km",
"other1": "x.96 inne",
"message-html": "<b>Zatrzymanie pociągu</b> na posterunku/szlaku {0} {'|'} {1} w km {2} celem {3}"
},
"2145": {
"text": "Na {signalbox1} na sygnalizatorze {signal1} {bold1}",
"bold1": "sygnał zezwalający jest nieważny, zatrzymać pociąg przed tym sygnalizatorem.",
"signalbox1": "x.1 posterunek",
"signal1": "x.2 sygnalizator",
"message-html": "Na {0} na sygnalizatorze {1} <b>sygnał zezwalający jest nieważny, zatrzymać pociąg przed tym sygnalizatorem.</b>"
},
"2150": {
"text": "{bold1} przejazdowych na posterunku/szlaku {br} {signalbox1} / {signalbox2} odnoszących się do przejazdu w km {km1}{br}{bold2}",
"bold1": "Wskazania tarcz ostrzegawczych",
"bold2": "są nieważne. Jazda z prędkością rozkładową.",
"signalbox1": "x.1 posterunek",
"signalbox2": "x.2 posterunek",
"km1": "x.3 km",
"message-html": "<b>Wskazania tarcz ostrzegawczych</b> przejazdowych na posterunku/szlaku {1} / {2} odnoszących się do przejazdu w km {3}, <b>są nieważne. Jazda z prędkością rozkładową.</b>"
},
"2155": {
"text": "<b>Uszkodzone urządzenia SHP</b> na {0} {1}|{2} odnoszące się do sygnalizatora {3}.",
"choice-1-a": "posterunku",
"choice-1-b": "szlaku",
"x1": "x.1 posterunek",
"x2": "x.2 posterunek",
"x3": "x.3 sygnalizator"
},
"2160": {
"text": "<b>Zmiana trasy</b> na odcinku od {0} do {1}, jazda przez {2} linią {3} z prędkością {4}.",
"x1": "x.1 posterunek",
"x2": "x.2 posterunek",
"x3": "x.3 posterunek",
"x4": "x.4 linia",
"x5": "x.5 km/h"
},
"2165": {
"text": "<b>Jazda z opuszczonymi pantografami</b> na odcinku od {0} do {1}.",
"x1": "x.1 km",
"x2": "x.2 km"
},
"2170": {
"text": "<b>Na odcinku</b> od {0} do {1} linii nr {2} <b>jazda pociągu z łącznością analogową.</b>",
"x1": "x.1 posterunek",
"x2": "x.2 posterunek",
"x3": "x.2 linia"
},
"2180": {
"text": "<b>Polecam jazdę po torze zamkniętym</b> nr {0} w kierunku {1} do km {2} zjazd do {3} do godz. {4}",
"x1": "x.1 tor",
"x2": "x.2 posterunek",
"x3": "x.3 km",
"x4": "x.4 posterunek",
"x5": "x.5 godzina"
},
"2181": {
"text": "<b>Tor zamknięty wolny od taboru</b>"
},
"2182": {
"text": "<b>Na torze pracuje pociąg</b> {0} w km {1}",
"x1": "x.1 numer pociągu",
"x2": "x.2 km"
},
"2183": {
"text": "<b>Na tor zostanie wyprawiony pociąg</b> {0} do km {1}",
"x1": "x.1 numer pociągu",
"x2": "x.2 km"
},
"2185": {
"text": "<b>Zezwalam na wstawienie PSD</b> na tor nr {0} w km {1} na szlaku | {2} | {3}",
"x1": "x.1 tor",
"x2": "x.2 km",
"x3": "x.3 posterunek",
"x4": "x.4 posterunek"
},
"23.10": {
"text": "<b>Nie przekraczać prędkości i zachować ostrożność:</b>",
"message-line-2": "<b>Na posterunku/szlaku</b> {0}/{1} tor nr {2} v {3} od {4} do {5} {6}",
"x1": "x.{0} posterunek",
"x2": "x.{0} posterunek",
"x3": "x.{0} tor",
"x4": "x.{0} km/h",
"x5": "x.{0} km",
"x6": "x.{0} km",
"x7": "x.{0} przyczyna"
},
"23.11": {
"text": "<b>Podawać sygnał „Baczność”</b>"
},
"23.20": {
"x96": "x.96 inne"
},
"footer": {
"V": "V Identyfikator maszynisty",
"W": "W Identyfikator nadawcy",
"Y": "Y Godzina",
"Z": "Z Identyfikator rozkazu pisemnego"
}
} }
} }
+123
View File
@@ -24,6 +24,129 @@ export const useStore = defineStore('store', {
chosenOrderType: 'orderN' as TOrder, chosenOrderType: 'orderN' as TOrder,
chosenLocalOrderId: '', chosenLocalOrderId: '',
orderData: {
header: {
A: '',
B: '',
C: '',
D: ''
},
instructions: [
{
key: '22',
name: '22',
active: false,
inputFields: {},
optionalFieldNames: []
},
{
key: '99',
name: '99',
active: false,
inputFields: {
x1: ''
},
optionalFieldNames: []
},
{
key: '2110',
name: '21.10',
active: false,
inputFields: {
track1: '',
signalbox1: '',
track2: '',
signalbox2: '',
signal1: '',
signal2: '',
signal3: ''
},
optionalFieldNames: ['signal1', 'signal2', 'signal3']
},
{
key: '2115',
name: '21.15',
active: false,
inputFields: {
track1: '',
signalbox1: '',
track2: '',
signal1: '',
signal2: '',
signal3: ''
},
optionalFieldNames: ['signal1', 'signal2', 'signal3']
},
{
key: '2120',
name: '21.20',
active: false,
inputFields: {
track1: '',
signalbox1: '',
signalbox2: ''
}
},
{
key: '2125',
name: '21.25',
active: false,
inputFields: {
select1: 'select1-a',
signalbox1: '',
track1: '',
km1: '',
hour1: ''
},
selectFields: {
select1: {
options: ['select1-a', 'select1-b']
}
}
},
{
key: '2135',
name: '21.35',
active: false,
inputFields: {
track1: '',
signalbox1: ''
}
},
{
key: '2140',
name: '21.40',
active: false,
inputFields: {
signalbox1: '',
signalbox2: '',
km1: '',
other1: ''
},
optionalFieldNames: ['signalbox2']
},
{
key: '2145',
name: '21.45',
active: false,
inputFields: {
signalbox1: '',
signal1: ''
}
},
{
key: '2150',
name: '21.50',
active: false,
inputFields: {
signalbox1: '',
signalbox2: '',
km1: ''
}
}
]
},
orderMode: 'OrderMessage', orderMode: 'OrderMessage',
orderFooter: { orderFooter: {
+192
View File
@@ -0,0 +1,192 @@
@use 'colors';
$darkModeTextCol: #eee;
.order {
width: 100%;
background-color: white;
color: black;
&.dark {
background-color: colors.$bgColDarker;
color: $darkModeTextCol;
}
@media screen and (max-width: 550px) {
font-size: 3vw;
}
}
table.order-table {
width: 100%;
overflow: auto;
border: 2px solid black;
border-collapse: collapse;
td {
border: 2px solid black;
border-collapse: collapse;
line-height: 1.25em;
text-align: justify;
vertical-align: top;
}
}
input.order-input {
max-width: 100%;
background-color: transparent;
outline: none;
border: none;
font-size: 1em;
text-align: center;
border-bottom: 2px dotted black;
&:focus-visible {
border-bottom: 2px solid colors.$accentCol;
}
&.row-checkbox + input::placeholder {
color: red;
}
&[type='checkbox']:focus-visible,
&[type='radio']:focus-visible {
outline: 2px solid colors.$accentCol;
}
&[type='checkbox'],
&[type='radio'] {
margin-top: 0.5em;
margin-right: 0.5em;
font-size: 0.8em;
color: black;
}
}
label.order-input-label {
display: block;
margin-top: 0.5rem;
font-size: 0.8rem;
}
select.order-select {
margin-top: 0.5em;
margin-right: 0.5em;
font-size: 0.8em;
color: black;
}
textarea.order-textarea {
width: 100%;
min-height: 200px;
resize: vertical;
&:focus-visible {
outline: 2px solid colors.$accentCol;
}
}
// Dark mode
.order.dark {
input.order-input {
border-color: $darkModeTextCol !important;
color: $darkModeTextCol !important;
&:focus-visible {
border-bottom: 2px solid colors.$accentCol !important;
}
&::placeholder {
color: #ccc !important;
}
}
select.order-select {
color: $darkModeTextCol !important;
border-color: $darkModeTextCol;
&:focus-visible {
border-color: colors.$accentCol;
}
}
select.order-select option,
textarea.order-textarea {
color: $darkModeTextCol !important;
border-color: $darkModeTextCol !important;
background-color: colors.$bgColDarker !important;
}
.horizontal-bar {
background-color: white;
}
.order_header,
.order_other,
table.order-table,
tr,
td {
border-color: $darkModeTextCol !important;
}
}
/* Instruction Checkbox */
.order-instruction-checkbox {
display: block;
position: relative;
text-align: center;
cursor: pointer;
font-weight: bold;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
& > input {
position: absolute;
opacity: 0;
height: 0;
width: 0;
cursor: pointer;
&:checked ~ .checkmark:after {
content: 'X';
}
&:focus-visible ~ .text {
text-decoration: underline;
outline: 1px solid black;
}
}
.checkmark {
display: block;
position: relative;
margin: 0 auto;
margin-bottom: 0.35em;
height: 1.3em;
width: 1.3em;
background-color: #eee;
border: 2px solid black;
background-color: gold;
&:after {
position: absolute;
content: '';
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
&:hover input ~ .checkmark {
background-color: #ffe44b;
}
}
+7 -9
View File
@@ -4,16 +4,15 @@
<div class="home"> <div class="home">
<div class="home_container"> <div class="home_container">
<div class="order_container"> <div class="order_container">
<SideBar /> <Order />
<OrderVue />
</div> </div>
<div class="message_container"> <div class="message_container">
<div class="message_nav"> <div class="message_nav">
<button class="g-button icon" @click="switchLanguages"> <!-- <button class="g-button icon" @click="switchLanguages">
<LanguagesIcon :size="18" /> <LanguagesIcon :size="18" />
<span style="margin-left: 0.25em">{{ $t('locale.' + store.currentAppLocale) }}</span> <span style="margin-left: 0.25em">{{ $t('locale.' + store.currentAppLocale) }}</span>
</button> </button> -->
<button <button
v-for="(action, i) in navActions" v-for="(action, i) in navActions"
@@ -38,18 +37,17 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import OrderVue from '../components/Order.vue'; import Order from '../components/Order/Order.vue';
import SideBar from '../components/SideBar.vue'; import SideBar from '../components/SideBar.vue';
import OrderMessage from '../components/OrderMessage.vue'; import OrderMessage from '../components/OrderMessage.vue';
import OrderList from '../components/OrderList.vue'; import OrderList from '../components/OrderList.vue';
import { useStore } from '../store/store'; import { useStore } from '../store/store';
import OrderHelper from '../components/OrderHelper.vue';
import OrderTrainPicker from '../components/OrderTrainPicker.vue'; import OrderTrainPicker from '../components/OrderTrainPicker.vue';
import { LanguagesIcon } from 'lucide-vue-next'; import { LanguagesIcon } from 'lucide-vue-next';
import StorageManager from '../managers/storageManager'; import StorageManager from '../managers/storageManager';
export default defineComponent({ export default defineComponent({
components: { OrderVue, SideBar, OrderHelper, LanguagesIcon }, components: { Order, SideBar, LanguagesIcon },
data() { data() {
return { return {
@@ -137,8 +135,8 @@ export default defineComponent({
} }
.order_container { .order_container {
width: 100%; width: 800px;
max-width: 600px; overflow: auto;
display: flex; display: flex;
align-items: start; align-items: start;