tagging release w.t.f.
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 5m58s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 9m2s

This commit is contained in:
2025-05-16 21:18:03 -04:00
parent 3c60c1b012
commit e484aa7e31
9 changed files with 314 additions and 135 deletions

View File

@@ -4,7 +4,7 @@ docker run -v $(pwd)/postgres:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=password \ -e POSTGRES_PASSWORD=password \
--rm --name postgres \ --rm --name postgres \
-p 5432:5432 \ -p 5432:5432 \
-d scr.siteworxpro.com/library/postgres:17 -d postgres:17
``` ```
```shell ```shell

View File

@@ -10,6 +10,7 @@ import (
"git.siteworxpro.com/reloading-manager/backend/handlers/primers" "git.siteworxpro.com/reloading-manager/backend/handlers/primers"
"git.siteworxpro.com/reloading-manager/backend/models/loads" "git.siteworxpro.com/reloading-manager/backend/models/loads"
"github.com/go-jet/jet/v2/postgres" "github.com/go-jet/jet/v2/postgres"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"net/http" "net/http"
@@ -43,13 +44,14 @@ type row struct {
} }
type loadResponseResults struct { type loadResponseResults struct {
Id string `json:"id"` Id string `json:"id"`
Cartridge string `json:"cartridge"` Cartridge string `json:"cartridge"`
Col float32 `json:"col"` CartridgeId string `json:"cartridge_id"`
Powder handlers.Powder `json:"powder"` Col float32 `json:"col"`
PowderGr float32 `json:"powder_gr"` Powder handlers.Powder `json:"powder"`
Primer primers.PrimerResponse `json:"primer"` PowderGr float32 `json:"powder_gr"`
Bullet bullets.BulletResponse `json:"bullet"` Primer primers.PrimerResponse `json:"primer"`
Bullet bullets.BulletResponse `json:"bullet"`
} }
type loadResponse struct { type loadResponse struct {
@@ -134,15 +136,40 @@ func Post(c echo.Context) error {
} }
func Get(c echo.Context) error { func Get(c echo.Context) error {
cTotal := make(chan ResultChan[int64])
id := c.Param("id")
cResults := make(chan ResultChan[[]loadResponseResults]) cResults := make(chan ResultChan[[]loadResponseResults])
if id != "" {
go execResultsQuery(cResults, c)
results := <-cResults
if results.Err != nil {
return results.Err
}
if len(results.Result) == 0 {
return handlers.NotFound(c, "load not found")
}
return c.JSON(http.StatusOK, handlers.Response[loadResponseResults]{Status: http.StatusText(http.StatusOK), Payload: results.Result[0]})
}
cTotal := make(chan ResultChan[int64])
go func(ch chan ResultChan[int64]) { go func(ch chan ResultChan[int64]) {
db := database.GetNewDatabase() db := database.GetNewDatabase()
defer db.Db.Close(context.Background()) defer func(Db *pgx.Conn, ctx context.Context) {
_ = Db.Close(ctx)
}(db.Db, context.Background())
q := getQuery(c, true) q := getQuery(c, true)
if q == nil {
ch <- ResultChan[int64]{Result: 0}
return
}
sql, params := q.Sql() sql, params := q.Sql()
var total int64 var total int64
@@ -157,101 +184,7 @@ func Get(c echo.Context) error {
} }
}(cTotal) }(cTotal)
go execResultsQuery(cResults, c)
go func(ch chan ResultChan[[]loadResponseResults]) {
db := database.GetNewDatabase()
defer db.Db.Close(context.Background())
q := getQuery(c, false)
fmt.Println(q.DebugSql())
sql, params := q.Sql()
rows, err := db.Db.Query(context.Background(), sql, params...)
if err != nil {
ch <- ResultChan[[]loadResponseResults]{Err: err}
return
}
results := make([]loadResponseResults, 0)
for rows.Next() {
row := row{}
err = rows.Scan(
&row.ID,
&row.Col,
&row.PowderGr,
&row.CartridgeID,
&row.CartridgeName,
&row.CartridgeMeta,
&row.BulletID,
&row.BulletName,
&row.BulletDiameter,
&row.BulletWeight,
&row.BulletMeta,
&row.BulletManufacturerName,
&row.BulletManufacturerUrl,
&row.PrimerID,
&row.PrimerName,
&row.PrimerMeta,
&row.PrimerManufacturerName,
&row.PrimerManufacturerUrl,
&row.PowderID,
&row.PowderName,
&row.PowderMeta,
&row.PowderManufacturerName,
&row.PowderManufacturerUrl,
)
if err != nil {
ch <- ResultChan[[]loadResponseResults]{Err: err}
return
}
results = append(results, loadResponseResults{
Id: row.ID.String(),
Cartridge: row.CartridgeName,
Col: row.Col,
Powder: handlers.Powder{
Id: row.PowderID.String(),
Name: row.PowderName,
Meta: string(row.PowderMeta),
Manufacturer: handlers.Manufacturer{
Name: row.PowderManufacturerName,
Url: row.PowderManufacturerUrl.String,
},
},
PowderGr: row.PowderGr,
Primer: primers.PrimerResponse{
ID: row.PrimerID.String(),
Name: row.PrimerName,
Manufacturer: handlers.Manufacturer{
Name: row.PrimerManufacturerName,
Url: row.PrimerManufacturerUrl.String,
},
},
Bullet: bullets.BulletResponse{
Id: row.BulletID.String(),
Name: row.BulletName,
Diameter: row.BulletDiameter,
Weight: row.BulletWeight,
Manufacturer: handlers.Manufacturer{
Name: row.BulletManufacturerName,
Url: row.BulletManufacturerUrl.String,
},
},
})
}
ch <- ResultChan[[]loadResponseResults]{Result: results}
}(cResults)
total := <-cTotal total := <-cTotal
if total.Err != nil { if total.Err != nil {
@@ -266,6 +199,108 @@ func Get(c echo.Context) error {
return c.JSON(http.StatusOK, handlers.Response[loadResponse]{Status: http.StatusText(http.StatusOK), Payload: loadResponse{Total: int(total.Result), Results: results.Result}}) return c.JSON(http.StatusOK, handlers.Response[loadResponse]{Status: http.StatusText(http.StatusOK), Payload: loadResponse{Total: int(total.Result), Results: results.Result}})
} }
func execResultsQuery(ch chan ResultChan[[]loadResponseResults], c echo.Context) {
db := database.GetNewDatabase()
defer func(Db *pgx.Conn, ctx context.Context) {
_ = Db.Close(ctx)
}(db.Db, context.Background())
q := getQuery(c, false)
if q == nil {
ch <- ResultChan[[]loadResponseResults]{Result: []loadResponseResults{}}
return
}
fmt.Println(q.DebugSql())
sql, params := q.Sql()
rows, err := db.Db.Query(context.Background(), sql, params...)
if err != nil {
ch <- ResultChan[[]loadResponseResults]{Err: err}
return
}
results := make([]loadResponseResults, 0)
for rows.Next() {
row := row{}
err = rows.Scan(
&row.ID,
&row.Col,
&row.PowderGr,
&row.CartridgeID,
&row.CartridgeName,
&row.CartridgeMeta,
&row.BulletID,
&row.BulletName,
&row.BulletDiameter,
&row.BulletWeight,
&row.BulletMeta,
&row.BulletManufacturerName,
&row.BulletManufacturerUrl,
&row.PrimerID,
&row.PrimerName,
&row.PrimerMeta,
&row.PrimerManufacturerName,
&row.PrimerManufacturerUrl,
&row.PowderID,
&row.PowderName,
&row.PowderMeta,
&row.PowderManufacturerName,
&row.PowderManufacturerUrl,
)
if err != nil {
ch <- ResultChan[[]loadResponseResults]{Err: err}
return
}
results = append(results, loadResponseResults{
Id: row.ID.String(),
Cartridge: row.CartridgeName,
CartridgeId: row.CartridgeID.String(),
Col: row.Col,
Powder: handlers.Powder{
Id: row.PowderID.String(),
Name: row.PowderName,
Meta: string(row.PowderMeta),
Manufacturer: handlers.Manufacturer{
Name: row.PowderManufacturerName,
Url: row.PowderManufacturerUrl.String,
},
},
PowderGr: row.PowderGr,
Primer: primers.PrimerResponse{
ID: row.PrimerID.String(),
Name: row.PrimerName,
Manufacturer: handlers.Manufacturer{
Name: row.PrimerManufacturerName,
Url: row.PrimerManufacturerUrl.String,
},
},
Bullet: bullets.BulletResponse{
Id: row.BulletID.String(),
Name: row.BulletName,
Diameter: row.BulletDiameter,
Weight: row.BulletWeight,
Manufacturer: handlers.Manufacturer{
Name: row.BulletManufacturerName,
Url: row.BulletManufacturerUrl.String,
},
},
})
}
ch <- ResultChan[[]loadResponseResults]{Result: results}
}
func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement { func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement {
l := table.Loads.AS("l") l := table.Loads.AS("l")
ctg := table.Cartridges.AS("c") ctg := table.Cartridges.AS("c")
@@ -289,7 +324,6 @@ func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement {
if countOnly { if countOnly {
q = tb.SELECT(postgres.COUNT(l.ID).AS("total")) q = tb.SELECT(postgres.COUNT(l.ID).AS("total"))
} else { } else {
q = tb.SELECT( q = tb.SELECT(
// Load // Load
l.ID.AS("id"), l.ID.AS("id"),
@@ -329,6 +363,17 @@ func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement {
// where expressions // where expressions
expressions := make([]postgres.BoolExpression, 0) expressions := make([]postgres.BoolExpression, 0)
if c.Param("id") != "" {
uuid, err := handlers.ParseUuid(c.Param("id"))
if err != nil {
return nil
}
q = q.WHERE(l.ID.EQ(postgres.UUID(uuid)))
return q
}
if c.QueryParam("cartridge_id") != "" { if c.QueryParam("cartridge_id") != "" {
ids := strings.Split(c.QueryParam("cartridge_id"), ",") ids := strings.Split(c.QueryParam("cartridge_id"), ",")
if len(ids) > 0 { if len(ids) > 0 {
@@ -438,13 +483,15 @@ func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement {
if limit == "" { if limit == "" {
limit = "50" limit = "50"
} }
offset := c.QueryParam("offset")
if offset == "" { pageInt := handlers.ParseInt64OrDefault(c.QueryParam("page"), 1)
offset = "0" if pageInt < 1 {
pageInt = 1
} }
offset := (pageInt - 1) * handlers.ParseInt64OrDefault(limit, 50)
q = q.LIMIT(handlers.ParseInt64OrDefault(limit, 50)). q = q.LIMIT(handlers.ParseInt64OrDefault(limit, 50)).
OFFSET(handlers.ParseInt64OrDefault(offset, 0)) OFFSET(offset)
return q return q
} }

View File

@@ -98,6 +98,7 @@ func main() {
// loads // loads
e.GET("/load", loads.Get) e.GET("/load", loads.Get)
e.GET("/load/:id", loads.Get)
e.POST("/load", loads.Post) e.POST("/load", loads.Post)
addr := fmt.Sprintf("0.0.0.0:%s", Port.GetEnvString("8080")) addr := fmt.Sprintf("0.0.0.0:%s", Port.GetEnvString("8080"))

View File

@@ -0,0 +1,49 @@
<template>
<div class="loader" v-if="loading">
<div class="flex flex-col justify-center items-center">
<ProgressSpinner :style="{ width: '50px', height: '50px' }" strokeWidth="5" />
</div>
<div class="flex flex-row justify-center items-center">
<span class="text-2xl">{{ message }}</span>
</div>
</div>
</template>
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'
const ProgressSpinner = defineAsyncComponent(() => import('primevue/progressspinner'))
defineProps({
loading: {
type: Boolean,
default: false
},
message: {
type: String,
default: 'Loading...'
}
})
</script>
<style scoped lang="scss">
.loader {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(9, 5, 5, 0.56);
z-index: 1000;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.text-2xl {
margin-top: 10px;
font-size: 24px;
font-weight: bold;
color: #ffffff;
}
}
</style>

View File

@@ -5,4 +5,5 @@ export const icons = {
upload: 'fa-thin fa-sharp fa-upload', upload: 'fa-thin fa-sharp fa-upload',
save: 'fa-thin fa-sharp fa-floppy-disk', save: 'fa-thin fa-sharp fa-floppy-disk',
delete: 'fa-thin fa-sharp fa-trash', delete: 'fa-thin fa-sharp fa-trash',
loading: 'fa-solid fa-sharp fa-cog fa-spin',
} }

View File

@@ -1,7 +1,8 @@
<template> <template>
<Card class="md:w-2/3 w-full"> <Card class="md:w-2/3 w-full">
<template #title> <template #title>
Add New Load <span v-if="route.params.id">Edit Load</span>
<span v-else>Add New Load</span>
</template> </template>
<template #content> <template #content>
<div class="grid grid-cols-1"> <div class="grid grid-cols-1">
@@ -103,6 +104,7 @@
</template> </template>
</Dialog> </Dialog>
<FullScreenLoader :loading="loading" />
</template> </template>
<script lang="ts"> <script lang="ts">
interface Select { interface Select {
@@ -121,13 +123,16 @@ import { defineAsyncComponent, onMounted, ref } from 'vue'
import { Primers } from '../../types/primers' import { Primers } from '../../types/primers'
import { Powder } from '../../types/powder' import { Powder } from '../../types/powder'
import axios from 'axios' import axios from 'axios'
import { Response } from '../../types/Response' import { Load, Response } from '../../types/Response'
import { icons } from '../../lib/icons.ts' import { icons } from '../../lib/icons.ts'
import { FileUploadSelectEvent } from 'primevue/fileupload' import { FileUploadSelectEvent } from 'primevue/fileupload'
import useVuelidate from '@vuelidate/core' import useVuelidate from '@vuelidate/core'
import { required } from '@vuelidate/validators' import { required } from '@vuelidate/validators'
import { useToast } from 'primevue/usetoast' import { useToast } from 'primevue/usetoast'
import router from '../../router' import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()
const Card = defineAsyncComponent(() => import('primevue/card')) const Card = defineAsyncComponent(() => import('primevue/card'))
const Select = defineAsyncComponent(() => import('primevue/select')) const Select = defineAsyncComponent(() => import('primevue/select'))
@@ -138,6 +143,7 @@ const InputMask = defineAsyncComponent(() => import('primevue/inputmask'))
const FileUpload = defineAsyncComponent(() => import('primevue/fileupload')) const FileUpload = defineAsyncComponent(() => import('primevue/fileupload'))
const Dialog = defineAsyncComponent(() => import('primevue/dialog')) const Dialog = defineAsyncComponent(() => import('primevue/dialog'))
const Message = defineAsyncComponent(() => import('primevue/message')) const Message = defineAsyncComponent(() => import('primevue/message'))
const FullScreenLoader = defineAsyncComponent(() => import('../../components/FullScreenLoader.vue'))
const toast = useToast() const toast = useToast()
@@ -145,6 +151,7 @@ const bullets = ref<Select[]>([])
const primers = ref<Select[]>([]) const primers = ref<Select[]>([])
const powders = ref<Select[]>([]) const powders = ref<Select[]>([])
const cartridges = ref<Select[]>([]) const cartridges = ref<Select[]>([])
const loading = ref(false)
const cartridgeName = ref('') const cartridgeName = ref('')
const addCartridgeDialog = ref(false) const addCartridgeDialog = ref(false)
@@ -191,21 +198,18 @@ const fetchBullets = async () => {
bullets.value.push({ label: `${bullet.manufacturer.name} ${bullet.weight}gr ${bullet.name}`, value: bullet.id }) bullets.value.push({ label: `${bullet.manufacturer.name} ${bullet.weight}gr ${bullet.name}`, value: bullet.id })
}) })
} }
const fetchPrimers = async () => { const fetchPrimers = async () => {
const response = await axios.get<any, Response<Primers[]>>(`${import.meta.env.VITE_API}/primer`) const response = await axios.get<any, Response<Primers[]>>(`${import.meta.env.VITE_API}/primer`)
response.data.payload.forEach((primer: Primers) => { response.data.payload.forEach((primer: Primers) => {
primers.value.push({ label: `${primer.manufacturer.name} ${primer.name}`, value: primer.id }) primers.value.push({ label: `${primer.manufacturer.name} ${primer.name}`, value: primer.id })
}) })
} }
const fetchPowders = async () => { const fetchPowders = async () => {
const response = await axios.get<any, Response<Powder[]>>(`${import.meta.env.VITE_API}/powder`) const response = await axios.get<any, Response<Powder[]>>(`${import.meta.env.VITE_API}/powder`)
response.data.payload.forEach((powder: Powder) => { response.data.payload.forEach((powder: Powder) => {
powders.value.push({ label: `${powder.manufacturer.name} ${powder.name}`, value: powder.id }) powders.value.push({ label: `${powder.manufacturer.name} ${powder.name}`, value: powder.id })
}) })
} }
const fetchCartridges = async () => { const fetchCartridges = async () => {
cartridges.value = [] cartridges.value = []
@@ -214,7 +218,6 @@ const fetchCartridges = async () => {
cartridges.value.push({ label: `${cartridge.name}`, value: cartridge.id }) cartridges.value.push({ label: `${cartridge.name}`, value: cartridge.id })
}) })
} }
const addCartridgeName = async () => { const addCartridgeName = async () => {
if (cartridgeName.value === '') { if (cartridgeName.value === '') {
return return
@@ -237,7 +240,6 @@ const addCartridgeName = async () => {
cartridgeName.value = '' cartridgeName.value = ''
addCartridgeDialog.value = false addCartridgeDialog.value = false
} }
const add = async () => { const add = async () => {
v$.value.$touch() v$.value.$touch()
@@ -284,14 +286,46 @@ const add = async () => {
life: 3000, life: 3000,
}) })
} }
} }
const fetchLoad = async () => {
if (!route.params.id) {
return
}
loading.value = true
const response = await axios.get<any, Response<Load>>(`${import.meta.env.VITE_API}/load/${route.params.id}`)
if (response.data.payload) {
load.value.cartridge = response.data.payload.cartridge_id
load.value.bullet = response.data.payload.bullet.id
load.value.powder = response.data.payload.powder.id
load.value.powderGrs = response.data.payload.powder_gr
load.value.primer = response.data.payload.primer.id
} else {
toast.add({
severity: 'error',
summary: 'Error',
detail: 'Load not found',
life: 3000,
})
await router.push('/loads')
}
loading.value = false
}
onMounted(() => { onMounted(() => {
fetchBullets() fetchBullets()
fetchPrimers() fetchPrimers()
fetchPowders() fetchPowders()
fetchCartridges() fetchCartridges()
if (route.params.id) {
fetchLoad()
}
}) })
</script> </script>

View File

@@ -8,13 +8,15 @@
:value="loads" :value="loads"
filterDisplay="row" filterDisplay="row"
paginator paginator
:rowsPerPageOptions="[5, 10, 20, 50]"
size="small" size="small"
:sortField="sortField" :sortField="sortField"
:sortOrder="sortOrder" :sortOrder="sortOrder"
@update:sortField="(e: string) => {sortField = e; fetchLoads()}" @update:sortField="(e: string) => {sortField = e; fetchLoads()}"
@update:sortOrder="(e: number | undefined) => {sortOrder = e; fetchLoads()}" @update:sortOrder="(e: number | undefined) => {sortOrder = e; fetchLoads()}"
@page="updatePagination"
:rows="rowsPerPage"
lazy lazy
:rows="50"
:totalRecords="total" :totalRecords="total"
:loading="loading" :loading="loading"
> >
@@ -42,7 +44,9 @@
@change="fetchLoads" /> @change="fetchLoads" />
</template> </template>
<template #body="{ data }"> <template #body="{ data }">
{{ data.bullet.manufacturer.name }} <a target="_blank" :href="data.bullet.manufacturer.url">
{{ data.bullet.manufacturer.name }}
</a>
</template> </template>
</Column> </Column>
<Column field="bullet_name" header="Bullet" :sortable="true" :showFilterMenu="false"> <Column field="bullet_name" header="Bullet" :sortable="true" :showFilterMenu="false">
@@ -63,7 +67,9 @@
@change="fetchLoads" /> @change="fetchLoads" />
</template> </template>
<template #body="{ data }"> <template #body="{ data }">
{{ data.primer.manufacturer.name }} <a target="_blank" :href="data.primer.manufacturer.url">
{{ data.primer.manufacturer.name }}
</a>
</template> </template>
</Column> </Column>
<Column field="primer_name" header="Primer" :sortable="true" :showFilterMenu="false"> <Column field="primer_name" header="Primer" :sortable="true" :showFilterMenu="false">
@@ -83,7 +89,9 @@
@change="fetchLoads" /> @change="fetchLoads" />
</template> </template>
<template #body="{ data }"> <template #body="{ data }">
{{ data.powder.manufacturer.name }} <a target="_blank" :href="data.powder.manufacturer.url">
{{ data.powder.manufacturer.name }}
</a>
</template> </template>
</Column> </Column>
@@ -104,8 +112,13 @@
</Column> </Column>
<Column field="edit" header="Edit"> <Column field="edit" header="Edit">
<template #body> <template #body="{ data }">
<Button size="small" text :icon="icons.edit" /> <Button
size="small"
text
:icon="icons.edit"
@click="router.push('/loads/edit/' + data.id)"
/>
</template> </template>
</Column> </Column>
</DataTable> </DataTable>
@@ -116,22 +129,13 @@
import { Bullet } from '../../types/bullet' import { Bullet } from '../../types/bullet'
import { Powder } from '../../types/powder' import { Powder } from '../../types/powder'
import { Primers } from '../../types/primers' import { Primers } from '../../types/primers'
import { Load } from '../../types/Response'
interface LoadResponse { interface LoadResponse {
total: number total: number
results: Load[] results: Load[]
} }
interface Load {
id: string
bullet: Bullet
cartridge: string
powder: Powder
powder_gr: number
primer: Primers
col: number
}
interface Option { interface Option {
label: string label: string
value: string value: string
@@ -143,6 +147,7 @@ import { Response } from '../../types/Response'
import axios from 'axios' import axios from 'axios'
import Column from 'primevue/column' import Column from 'primevue/column'
import { icons } from '../../lib/icons.ts' import { icons } from '../../lib/icons.ts'
import router from '../../router'
const DataTable = defineAsyncComponent(() => import('primevue/datatable')) const DataTable = defineAsyncComponent(() => import('primevue/datatable'))
const Card = defineAsyncComponent(() => import('primevue/card')) const Card = defineAsyncComponent(() => import('primevue/card'))
@@ -151,6 +156,8 @@ const MultiSelect = defineAsyncComponent(() => import('primevue/multiselect'))
const loads = ref<Load[]>([]) const loads = ref<Load[]>([])
const total = ref(0) const total = ref(0)
const rowsPerPage = ref(50)
const page = ref(1)
const loading = ref(true) const loading = ref(true)
// use local storage to store the selected filters // use local storage to store the selected filters
@@ -181,6 +188,14 @@ const powderManufacturerSelected = ref<string[]>(localStorageFilters.powderManuf
const powderOptions = ref<Option[]>([]) const powderOptions = ref<Option[]>([])
const powderSelected = ref<string[]>(localStorageFilters.powderSelected ?? []) const powderSelected = ref<string[]>(localStorageFilters.powderSelected ?? [])
const updatePagination = (e: { page: number, rows: number }) => {
console.log(e)
page.value = e.page + 1
rowsPerPage.value = e.rows
fetchLoads()
}
const fetchLoads = async () => { const fetchLoads = async () => {
loading.value = true loading.value = true
@@ -220,6 +235,9 @@ const fetchLoads = async () => {
searchParams.unshift(`powder_id=${powderSelected.value.join(',')}`) searchParams.unshift(`powder_id=${powderSelected.value.join(',')}`)
} }
searchParams.unshift(`limit=${rowsPerPage.value}`)
searchParams.unshift(`page=${page.value}`)
localStorage.setItem(localStorageKey, JSON.stringify({ localStorage.setItem(localStorageKey, JSON.stringify({
cartridgeSelected: cartridgeSelected.value, cartridgeSelected: cartridgeSelected.value,
bulletManufacturerSelected: bulletManufacturerSelected.value, bulletManufacturerSelected: bulletManufacturerSelected.value,
@@ -269,6 +287,11 @@ onMounted(() => {
value: primer.manufacturer.id, value: primer.manufacturer.id,
})) }))
// dedupe the primer Manufacturer options
primerManufacturerOptions.value = primerManufacturerOptions.value.filter((option, index, self) =>
index === self.findIndex((o) => o.value === option.value)
)
primerOptions.value = resp.data.payload.map((primer) => ({ primerOptions.value = resp.data.payload.map((primer) => ({
label: primer.name, label: primer.name,
value: primer.id, value: primer.id,
@@ -281,6 +304,12 @@ onMounted(() => {
value: powder.manufacturer.id, value: powder.manufacturer.id,
})) }))
// dedupe the powder Manufacturer options
powderManufacturerOptions.value = powderManufacturerOptions.value.filter((option, index, self) =>
index === self.findIndex((o) => o.value === option.value)
)
powderOptions.value = resp.data.payload.map((powder) => ({ powderOptions.value = resp.data.payload.map((powder) => ({
label: powder.name, label: powder.name,
value: powder.id, value: powder.id,

View File

@@ -61,6 +61,10 @@ const routes = [
path: '/loads/search', path: '/loads/search',
component: () => import('../pages/loads/Search.vue'), component: () => import('../pages/loads/Search.vue'),
}, },
{
path: '/loads/edit/:id',
component: () => import('../pages/loads/Add.vue'),
},
] as RouteRecordRaw[] ] as RouteRecordRaw[]
const router = createRouter({ const router = createRouter({

View File

@@ -1,4 +1,18 @@
import {AxiosResponse} from "axios"; import {AxiosResponse} from "axios";
import { Bullet } from './bullet'
import { Powder } from './powder'
import { Primers } from './primers'
interface Load {
id: string
bullet: Bullet
cartridge: string
cartridge_id: string
powder: Powder
powder_gr: number
primer: Primers
col: number
}
export interface Response<T> extends AxiosResponse { export interface Response<T> extends AxiosResponse {
data: { data: {