Skip to content

Commit

Permalink
feat: added warning/info borders and some car number validation.
Browse files Browse the repository at this point in the history
Need to fix a problematic bug surrounding empty car numbers though
  • Loading branch information
Stoolbend committed Feb 25, 2024
1 parent dc00f27 commit ceda9a2
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 5 deletions.
76 changes: 72 additions & 4 deletions src/components/EntryListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ import DriverSelectModal from '@/components/DriverSelectModal.vue'
import EntryOptionToggle from '@/components/EntryOptionToggle.vue'
import { useGameData } from '@/composables/gameData'
import { EntryListDriver, EntryListEntry } from '@/lib/gameFiles'
import { onMounted } from 'vue'
import { computed, ref, watch, watchEffect } from 'vue'
import { useModal } from 'vue-final-modal'
const props = defineProps<{
entry: EntryListEntry
raceNumbers: number[]
}>()
const emit = defineEmits<{
(e: 'updated', value: EntryListEntry): void
Expand Down Expand Up @@ -62,14 +64,77 @@ function deleteDriver(entry: EntryListEntry, driver: EntryListDriver) {
}
//#endregion
//#region Warnings & indicators
//#region Car number processing
const raceNumber = ref<string>('')
//TODO Fix a bug here where emptying the car number sets the field to null, and the entry disappears.
onMounted(() => {
if (props.entry.raceNumber == null || props.entry.raceNumber < 0 || props.entry.raceNumber > 999) {
props.entry.raceNumber = 1
raceNumber.value = (1).toString()
} else raceNumber.value = props.entry.raceNumber.toString()
})
watch(raceNumber, (value) => {
const parsedNumber = Number.parseInt(value)
if (parsedNumber == null || parsedNumber < 0 || parsedNumber > 999) {
props.entry.raceNumber = 1
raceNumber.value = (1).toString()
} else props.entry.raceNumber = Number.parseInt(value)
})
//#endregion
//#region Warnings, indicators & validation
enum AlertSeverity {
None,
Info,
Warning,
Critical,
}
const border = computed(() => {})
const alertLevel = ref<AlertSeverity>(AlertSeverity.None)
const alertMessage = ref<string>()
const border = computed(() => {
switch (alertLevel.value) {
case AlertSeverity.Info:
return 'alert-info'
case AlertSeverity.Warning:
return 'alert-warning'
case AlertSeverity.Critical:
return 'alert-danger'
default:
return ''
}
})
function validateRaceNumber() {
const parsedNumber = Number.parseInt(props.entry.raceNumber.toString())
// Check it's a valid integer
if (Number.isNaN(parsedNumber)) {
alertMessage.value = 'Car number must be set'
return false
}
// Check it's not a duplicate of another car
if (props.raceNumbers.filter((n) => n === parsedNumber).length > 1) {
alertMessage.value = 'Car number is not unique'
return false
}
return true
}
// Check properties and display warnings
watchEffect(() => {
// Critical problems
if (!validateRaceNumber()) {
alertLevel.value = AlertSeverity.Critical
return
}
// Warning problems
// Informational messages
if (props.entry.drivers.length < 1) {
alertLevel.value = AlertSeverity.Info
alertMessage.value = 'Car has no drivers'
return
}
// Clear the alerts if nothing is wrong
alertLevel.value = AlertSeverity.None
alertMessage.value = undefined
})
//#endregion
</script>

Expand All @@ -78,14 +143,17 @@ const border = computed(() => {})
<div class="col-12 col-md-1 d-flex flex-column text-center gap-1">
<div class="car-number">
<div>Car</div>
<b-form-input v-model="entry.raceNumber" class="big-input" size="lg" />
<b-form-input v-model="raceNumber" type="number" min="0" max="999" step="1" class="big-input" size="lg" required placeholder="-" />
</div>
<div class="grid-position">
<div>Grid pos.</div>
<b-form-input v-model="entry.defaultGridPosition" class="big-input" size="lg" placeholder="-" />
<b-form-input v-model="entry.defaultGridPosition" type="number" min="0" max="99" step="1" class="big-input" size="lg" placeholder="-" />
</div>
</div>
<div class="drivers col-12 col-md-6">
<div v-if="alertMessage" class="alert py-1 m-0" :class="border" role="alert">
{{ alertMessage }}
</div>
<div v-for="(driver, i) in entry.drivers" :key="driver.playerID" class="driver">
<DriverEntryInlineForm v-model="entry.drivers[i]" />
<div class="driver-controls">
Expand Down
8 changes: 7 additions & 1 deletion src/views/EntryListView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ import { EntryList, EntryListEntry } from '@/lib/gameFiles'
import { getNextAvailableCarNumber, getPlatformClass } from '@/lib/utils'
import { useDriverStore } from '@/stores/drivers'
import { Platform, PlatformOptions } from '@/stores/settings'
import { cloneDeep } from 'lodash-es'
import { computed, ref, watch, watchEffect } from 'vue'
const data = ref<EntryList>()
const driverStore = useDriverStore()
const raceNumbers = computed(() => {
if (!data.value) return []
return data.value.entries.map((e) => e.raceNumber)
})
//#region Default platform
const defaultPlatform = ref<Platform>(driverStore.defaultPlatform)
const defaultPlatformClass = computed(() => getPlatformClass(defaultPlatform.value))
Expand Down Expand Up @@ -67,7 +73,7 @@ function deleteEntry(entry: EntryListEntry) {
<b-button variant="success" @click="addEntry"><i class="bi bi-plus me-1" />Add car</b-button>
</div>
<div class="entries">
<EntryListItem v-for="(entry, i) in data.entries" :key="entry.raceNumber" :entry="entry" @delete="deleteEntry" />
<EntryListItem v-for="(entry, i) in data.entries" :key="entry.raceNumber" :entry="entry" :race-numbers="raceNumbers" @delete="deleteEntry" />
</div>
</template>
<hr />
Expand Down

0 comments on commit ceda9a2

Please sign in to comment.