No changes made

This commit is contained in:
2025-04-16 12:47:04 -04:00
commit 1ed3b0c2d4
98 changed files with 8857 additions and 0 deletions

View File

@@ -0,0 +1,297 @@
<template>
<Card class="md:w-2/3 w-full">
<template #title>
Add New Load
</template>
<template #content>
<div class="grid grid-cols-1">
<div>
Cartridge
</div>
<div class="flex flex-row items-center">
<div class="grow mr-3">
<Select v-model="load.cartridge" :options="cartridges" optionLabel="label" optionValue="value"
class="w-full" />
<Message v-if="v$.$dirty && v$.cartridge.$invalid" :value="false" size="small" severity="error"
variant="simple">Cartridge Required
</Message>
</div>
<div class="cursor-pointer" @click="addCartridgeDialog = true">
<i :class="icons.add" class="fa-2x" />
</div>
</div>
<div class="mt-3 mr-3">
Bullet
</div>
<div class="w-full mt-3">
<Select v-model="load.bullet" :invalid="v$.$dirty && v$.bullet.$invalid" :options="bullets"
optionLabel="label" optionValue="value" class="w-full" />
<Message v-if="v$.$dirty && v$.bullet.$invalid" :value="false" size="small" severity="error" variant="simple">
Bullet Required
</Message>
</div>
<div class="mt-3 mr-3">
Powder
</div>
<div class="flex flex-row">
<div class="grow mr-3">
<Select v-model="load.powder" :options="powders" optionLabel="label" optionValue="value" class="w-full" />
<Message v-if="v$.$dirty && v$.powder.$invalid" :value="false" size="small" severity="error"
variant="simple">Powder Required
</Message>
</div>
<div>
<InputNumber v-model="load.powderGrs" placeholder="00.0 gr" suffix=" gr" :minFractionDigits="1"
:maxFractionDigits="1" :min="0"
:max="1000" class="w-full" />
<Message v-if="v$.$dirty && v$.powderGrs.$invalid" :value="false" size="small" severity="error"
variant="simple">Grains Required
</Message>
</div>
</div>
<div class="mt-3 mr-3">
Primer
</div>
<div class="w-full mt-3">
<Select v-model="load.primer" :options="primers" optionLabel="label" optionValue="value" class="w-full" />
<Message v-if="v$.$dirty && v$.primer.$invalid" :value="false" size="small" severity="error"
variant="simple">Primer Required
</Message>
</div>
<div class="mt-3 mr-3">
COL
</div>
<div class="w-full mt-3">
<InputMask placeholder="0.000" v-model="load.col" mask="9.999" class="w-full" />
<Message v-if="v$.$dirty && v$.col.$invalid" :value="false" size="small" severity="error"
variant="simple">COL Required
</Message>
</div>
<div class="w-full mt-5">
<label>Picture</label>
<Message v-if="v$.$dirty && !file" :value="false" size="small" severity="error"
variant="simple">Picture Required
</Message>
<FileUpload v-model="file" mode="basic" @select="fileSelected" customUpload />
</div>
</div>
</template>
<template #footer>
<Button label="Add" :icon="icons.add" @click="add" />
</template>
</Card>
<Dialog @update:visible="addCartridgeDialog = false" modal :visible="addCartridgeDialog" :style="{ width: '35rem' }">
<template #header>
Add Cartridge
</template>
<div class="grid grid-cols-1">
<div>
Name
</div>
<div class="w-full">
<InputText :invalid="cartridgeName === ''" v-model="cartridgeName" class="w-full" />
</div>
</div>
<template #footer>
<Button :disabled="cartridgeName === ''" label="Add" :icon="icons.add" @click="addCartridgeName" />
</template>
</Dialog>
</template>
<script lang="ts">
interface Select {
label: string
value: string
}
interface Cartridge {
id: string
name: string
}
</script>
<script lang="ts" setup>
import { Bullet } from '../../types/bullet'
import { defineAsyncComponent, onMounted, ref } from 'vue'
import { Primers } from '../../types/primers'
import { Powder } from '../../types/powder'
import axios from 'axios'
import { Response } from '../../types/Response'
import { icons } from '../../lib/icons.ts'
import { FileUploadSelectEvent } from 'primevue/fileupload'
import useVuelidate from '@vuelidate/core'
import { required } from '@vuelidate/validators'
import { useToast } from 'primevue/usetoast'
import router from '../../router'
const Card = defineAsyncComponent(() => import('primevue/card'))
const Select = defineAsyncComponent(() => import('primevue/select'))
const Button = defineAsyncComponent(() => import('primevue/button'))
const InputNumber = defineAsyncComponent(() => import('primevue/inputnumber'))
const InputText = defineAsyncComponent(() => import('primevue/inputtext'))
const InputMask = defineAsyncComponent(() => import('primevue/inputmask'))
const FileUpload = defineAsyncComponent(() => import('primevue/fileupload'))
const Dialog = defineAsyncComponent(() => import('primevue/dialog'))
const Message = defineAsyncComponent(() => import('primevue/message'))
const toast = useToast()
const bullets = ref<Select[]>([])
const primers = ref<Select[]>([])
const powders = ref<Select[]>([])
const cartridges = ref<Select[]>([])
const cartridgeName = ref('')
const addCartridgeDialog = ref(false)
const file = ref<File | null>(null)
const fileSelected = (e: FileUploadSelectEvent) => {
file.value = e.files[0]
}
const load = ref({
bullet: '',
cartridge: '',
powder: '',
powderGrs: 0,
primer: '',
col: '',
})
const v$ = useVuelidate({
bullet: { required },
cartridge: { required },
powder: { required },
powderGrs: {
required, min: function (val: number | null) {
if (!val) return false
return val > 0
},
},
primer: { required },
col: {
required, min: function (val: string | null) {
if (!val) return false
// regex to validate COL does not container _
return !val.includes('_')
},
},
}, load.value)
const fetchBullets = async () => {
const response = await axios.get<any, Response<Bullet[]>>(`${import.meta.env.VITE_API}/bullet`)
response.data.payload.forEach((bullet: Bullet) => {
bullets.value.push({ label: `${bullet.manufacturer.name} ${bullet.weight}gr ${bullet.name}`, value: bullet.id })
})
}
const fetchPrimers = async () => {
const response = await axios.get<any, Response<Primers[]>>(`${import.meta.env.VITE_API}/primer`)
response.data.payload.forEach((primer: Primers) => {
primers.value.push({ label: `${primer.manufacturer.name} ${primer.name}`, value: primer.id })
})
}
const fetchPowders = async () => {
const response = await axios.get<any, Response<Powder[]>>(`${import.meta.env.VITE_API}/powder`)
response.data.payload.forEach((powder: Powder) => {
powders.value.push({ label: `${powder.manufacturer.name} ${powder.name}`, value: powder.id })
})
}
const fetchCartridges = async () => {
cartridges.value = []
const response = await axios.get<any, Response<Cartridge[]>>(`${import.meta.env.VITE_API}/cartridge`)
response.data.payload.forEach((cartridge: Cartridge) => {
cartridges.value.push({ label: `${cartridge.name}`, value: cartridge.id })
})
}
const addCartridgeName = async () => {
if (cartridgeName.value === '') {
return
}
try {
await axios.post<any, Response<Cartridge>>(`${import.meta.env.VITE_API}/cartridge`, {
name: cartridgeName.value,
})
} catch (error) {
toast.add({
severity: 'error',
summary: 'Error',
detail: 'Error adding cartridge',
})
}
await fetchCartridges()
cartridgeName.value = ''
addCartridgeDialog.value = false
}
const add = async () => {
v$.value.$touch()
if (v$.value.$invalid || !file.value) {
toast.add({
severity: 'error',
summary: 'Error',
detail: 'Please correct all fields',
life: 3000,
})
return
}
const formData = new FormData()
formData.append('bullet_id', load.value.bullet)
formData.append('cartridge_id', load.value.cartridge)
formData.append('powder_id', load.value.powder)
formData.append('powder_gr', load.value.powderGrs.toString())
formData.append('primer_id', load.value.primer)
formData.append('col', load.value.col)
formData.append('photo', file.value)
try {
const response = await axios.post<any, Response<string>>(`${import.meta.env.VITE_API}/load`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
toast.add({
severity: 'success',
summary: 'Success',
detail: 'Load added',
life: 3000,
})
await router.push(`/loads/edit/${response.data.payload}`)
} catch (error) {
toast.add({
severity: 'error',
summary: 'Error',
detail: 'Error adding load',
life: 3000,
})
}
}
onMounted(() => {
fetchBullets()
fetchPrimers()
fetchPowders()
fetchCartridges()
})
</script>