From cba781d8099e39d0c54a9189e4a2a1bf13fbd0ce Mon Sep 17 00:00:00 2001 From: axolotle Date: Mon, 12 Aug 2024 23:49:16 +0200 Subject: [PATCH] feat: add useFormQuery to pair url params and a form --- app/src/composables/form.ts | 23 +++++++++++++++++++++++ app/src/helpers/commons.ts | 19 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/app/src/composables/form.ts b/app/src/composables/form.ts index d5ee06d6..68a7ae79 100644 --- a/app/src/composables/form.ts +++ b/app/src/composables/form.ts @@ -16,8 +16,10 @@ import type { WritableComputedRef, } from 'vue' import { computed, inject, provide, reactive, ref, toValue } from 'vue' +import { useRouter } from 'vue-router' import { APIBadRequestError, type APIError } from '@/api/errors' +import { fromEntries, getKeys } from '@/helpers/commons' import type { Obj } from '@/types/commons' import type { FormFieldDict } from '@/types/form' @@ -160,3 +162,24 @@ export function useArrayRule( }, {}) }) } + +export function useFormQuery( + props: T, + onUpdate?: () => T | undefined, +) { + const router = useRouter() + const formQuery = fromEntries( + getKeys(props).map((key) => [ + key, + computed({ + get: () => props[key], + set: (n) => { + const nextProps = onUpdate?.() ?? props + router.replace({ query: { ...nextProps, [key]: n } }) + }, + }), + ]) as { [K in keyof T]: [K, WritableComputedRef] }[keyof T][], + ) + + return formQuery +} diff --git a/app/src/helpers/commons.ts b/app/src/helpers/commons.ts index abe4cc55..13af6584 100644 --- a/app/src/helpers/commons.ts +++ b/app/src/helpers/commons.ts @@ -182,11 +182,30 @@ export function getFileContent( }) } +export function getKeys(obj: T): K { + return Object.keys(obj) as K +} + export function toEntries>( obj: T, ): { [K in keyof T]: [K, T[K]] }[keyof T][] { return Object.entries(obj) as { [K in keyof T]: [K, T[K]] }[keyof T][] } + +export function fromEntries< + const T extends ReadonlyArray, +>(entries: T): { [K in T[number] as K[0]]: K[1] } { + return Object.fromEntries(entries) as { [K in T[number] as K[0]]: K[1] } +} + +export function pick( + obj: T, + keys: K, +): Pick { + return Object.fromEntries(keys.map((key) => [key, obj[key]])) as Pick< + T, + K[number] + > } export function omit(