From 936958b43486b05f0a18119345ef1f5bfbeb890c Mon Sep 17 00:00:00 2001 From: Mamalizz Date: Fri, 3 Oct 2025 21:40:42 +0330 Subject: [PATCH] connected to new url param --- .../api/account/useGetAllNotifications.ts | 23 ++-- .../composables/api/orders/useGetAllOrders.ts | 31 +++-- .../api/orders/useGetTransaction.ts | 15 +-- .../api/products/useGetProducts.ts | 112 +++++++++++++----- .../api/resellers/useGetResellersProducts.ts | 99 ++++++++++++---- .../api/tickets/useGetAllTickets.ts | 17 +-- frontend/composables/global/useAppParams.ts | 71 +++++++++++ 7 files changed, 269 insertions(+), 99 deletions(-) create mode 100644 frontend/composables/global/useAppParams.ts diff --git a/frontend/composables/api/account/useGetAllNotifications.ts b/frontend/composables/api/account/useGetAllNotifications.ts index 68dfa77..94feb95 100644 --- a/frontend/composables/api/account/useGetAllNotifications.ts +++ b/frontend/composables/api/account/useGetAllNotifications.ts @@ -1,31 +1,28 @@ // imports import { useQuery } from "@tanstack/vue-query"; +import { useAppParams } from "~/composables/global/useAppParams"; import { API_ENDPOINTS, QUERY_KEYS } from "~/constants"; // types export type GetAllNotificationsResponse = ApiPaginated; -export type GetAllNotificationsRequest = { - sort: string | undefined; - status: string | undefined; - page: string | string[]; -}; - -const useGetAllNotifications = (params: ComputedRef) => { +const useGetAllNotifications = () => { // state const { $axios: axios } = useNuxtApp(); + const { sort, status, page } = useAppParams(); + // methods - const handleGetAllNotifications = async (params: GetAllNotificationsRequest) => { + const handleGetAllNotifications = async () => { const { data } = await axios.get(API_ENDPOINTS.account.notifications.get_all, { params: { - sort: params.sort, - filter: params.status, - offset: Number(params.page) * 10 - 10, + sort: sort.value ?? "created_at", + filter: status.value, + offset: Number(page.value) * 10 - 10, limit: 10, }, }); @@ -33,8 +30,8 @@ const useGetAllNotifications = (params: ComputedRef) }; return useQuery({ - queryKey: [QUERY_KEYS.notifications, params], - queryFn: () => handleGetAllNotifications(params.value), + queryKey: [QUERY_KEYS.notifications, sort, status, page], + queryFn: () => handleGetAllNotifications(), }); }; diff --git a/frontend/composables/api/orders/useGetAllOrders.ts b/frontend/composables/api/orders/useGetAllOrders.ts index ca9642b..0ae9525 100644 --- a/frontend/composables/api/orders/useGetAllOrders.ts +++ b/frontend/composables/api/orders/useGetAllOrders.ts @@ -1,6 +1,7 @@ // imports import { useQuery } from "@tanstack/vue-query"; +import { useAppParams } from "~/composables/global/useAppParams"; import { API_ENDPOINTS, QUERY_KEYS } from "~/constants"; // types @@ -13,32 +14,30 @@ export type GetAllOrdersRequest = { page: string | string[]; }; -const useGetAllOrders = (params: ComputedRef) => { - +const useGetAllOrders = () => { // state const { $axios: axios } = useNuxtApp(); + const { sort, status, page } = useAppParams(); + // methods - const handleGetAllOrders = async (params: GetAllOrdersRequest) => { - const { data } = await axios.get( - API_ENDPOINTS.orders.get_all, - { - params: { - sort: params.sort, - filter: params.status, - offset: Number(params.page) * 7 - 7, - limit: 7, - }, - } - ); + const handleGetAllOrders = async () => { + const { data } = await axios.get(API_ENDPOINTS.orders.get_all, { + params: { + sort: sort.value ?? "created_at", + filter: status.value, + offset: Number(page.value) * 10 - 10, + limit: 10, + }, + }); return data; }; return useQuery({ - queryKey: [QUERY_KEYS.orders, params], - queryFn: () => handleGetAllOrders(params.value), + queryKey: [QUERY_KEYS.orders, sort, status, page], + queryFn: () => handleGetAllOrders(), }); }; diff --git a/frontend/composables/api/orders/useGetTransaction.ts b/frontend/composables/api/orders/useGetTransaction.ts index 9951ac6..3d15dfa 100644 --- a/frontend/composables/api/orders/useGetTransaction.ts +++ b/frontend/composables/api/orders/useGetTransaction.ts @@ -1,31 +1,32 @@ // imports import { useQuery } from "@tanstack/vue-query"; +import { useAppParams } from "~/composables/global/useAppParams"; import { API_ENDPOINTS, QUERY_KEYS } from "~/constants"; // types export type GetTransactionResponse = Transaction; -export type GetTransactionRequest = string; - -const useGetTransaction = (params: ComputedRef) => { +const useGetTransaction = () => { // state const { $axios: axios } = useNuxtApp(); + const { tracking_code } = useAppParams(); + // methods - const handleGetTransaction = async (tc: GetTransactionRequest) => { + const handleGetTransaction = async () => { const { data } = await axios.get( - `${API_ENDPOINTS.orders.checkout.transaction}/${tc}` + `${API_ENDPOINTS.orders.checkout.transaction}/${tracking_code.value}` ); return data; }; return useQuery({ - queryKey: [QUERY_KEYS.transaction, params], - queryFn: () => handleGetTransaction(params.value), + queryKey: [QUERY_KEYS.transaction, tracking_code], + queryFn: () => handleGetTransaction(), }); }; diff --git a/frontend/composables/api/products/useGetProducts.ts b/frontend/composables/api/products/useGetProducts.ts index a842523..e53193b 100644 --- a/frontend/composables/api/products/useGetProducts.ts +++ b/frontend/composables/api/products/useGetProducts.ts @@ -1,57 +1,105 @@ // imports import { useQuery } from "@tanstack/vue-query"; +import { useAppParams } from "~/composables/global/useAppParams"; import { API_ENDPOINTS, QUERY_KEYS } from "~/constants"; // types export type GetProductsResponse = ApiPaginated; -export type GetProductsFilters = { - search?: string | undefined; - sort?: string | undefined; - category?: string | undefined; - price_gte: number; - price_lte: number; - has_discount?: boolean | undefined; - in_stock?: boolean | undefined; - page: number; -}; - // composable -const useGetProducts = (params?: ComputedRef) => { +const useGetProducts = () => { // state - const { $axios: axios } = useNuxtApp(); + const { $axios: axios, $queryClient: queryClient } = useNuxtApp(); + + const { search, sort, in_stock, has_discount, slug, price_gte, price_lte, page } = useAppParams(); + + const searchDebounced = refDebounced(search, 500); + + // computed + + const products_category = computed(() => { + if (Array.isArray(slug.value) && slug.value.length >= 2) { + return slug.value[1]; + } + return undefined; + }); + + const filters_clone = computed(() => { + return { + search, + sort, + in_stock, + has_discount, + slug, + price_gte, + price_lte, + }; + }); + + // watch + + watch( + () => filters_clone.value, + () => { + queryClient.cancelQueries({ + queryKey: [ + QUERY_KEYS.products, + searchDebounced, + sort, + in_stock, + has_discount, + products_category, + price_gte, + price_lte, + page, + ], + }); + page.value = 1; + }, + { + deep: true, + } + ); // methods - const handleGetProducts = async (params?: GetProductsFilters) => { - const { data } = await axios.get( - `${API_ENDPOINTS.products.get_all}`, - { - params: { - sort: params?.sort, - in_stock: params?.in_stock, - search: params?.search, - has_discount: params?.has_discount, - category: params?.category, - price_gte: params?.price_gte, - price_lte: params?.price_lte, - offset: Number(params?.page) * 15 - 15, - limit: 15 - } - } - ); + const handleGetProducts = async ({ signal }: { signal: AbortSignal }) => { + const { data } = await axios.get(`${API_ENDPOINTS.products.get_all}`, { + params: { + sort: sort.value || "newest", + in_stock: in_stock.value, + search: searchDebounced.value, + has_discount: has_discount.value, + category: products_category.value, + price_gte: price_gte.value, + price_lte: price_lte.value, + offset: Number(page.value) * 15 - 15, + limit: 15, + }, + signal, + }); return data; }; return useQuery({ staleTime: 60 * 1000, - queryKey: [QUERY_KEYS.products, params], - queryFn: () => handleGetProducts(params?.value) + queryKey: [ + QUERY_KEYS.products, + searchDebounced, + sort, + in_stock, + has_discount, + products_category, + price_gte, + price_lte, + page, + ], + queryFn: ({ signal }) => handleGetProducts({ signal }), }); }; diff --git a/frontend/composables/api/resellers/useGetResellersProducts.ts b/frontend/composables/api/resellers/useGetResellersProducts.ts index 269e70e..064e058 100644 --- a/frontend/composables/api/resellers/useGetResellersProducts.ts +++ b/frontend/composables/api/resellers/useGetResellersProducts.ts @@ -1,45 +1,86 @@ // imports import { useQuery } from "@tanstack/vue-query"; +import { useAppParams } from "~/composables/global/useAppParams"; import { API_ENDPOINTS, QUERY_KEYS } from "~/constants"; // types export type GetResellersProductsResponse = ApiPaginated; -export type GetResellersProductsFilters = { - search?: string | undefined; - sort?: string | undefined; - category?: string | undefined; - price_gte: number; - price_lte: number; - has_discount?: boolean | undefined; - in_stock?: boolean | undefined; - page: number; -}; - // composable -const useGetResellersProducts = (params?: ComputedRef) => { +const useGetResellersProducts = () => { // state - const { $axios: axios } = useNuxtApp(); + const { $axios: axios, $queryClient: queryClient } = useNuxtApp(); + + const { search, sort, in_stock, has_discount, slug, price_gte, price_lte, page } = useAppParams(); + + const searchDebounced = refDebounced(search, 500); + + // computed + + const products_category = computed(() => { + if (Array.isArray(slug.value) && slug.value.length >= 2) { + return slug.value[1]; + } + return undefined; + }); + + const filters_clone = computed(() => { + return { + search, + sort, + in_stock, + has_discount, + slug, + price_gte, + price_lte, + }; + }); + + // watch + + watch( + () => filters_clone.value, + () => { + queryClient.cancelQueries({ + queryKey: [ + QUERY_KEYS.products, + searchDebounced, + sort, + in_stock, + has_discount, + products_category, + price_gte, + price_lte, + page, + ], + }); + page.value = 1; + }, + { + deep: true, + } + ); // methods - const handleGetResellersProducts = async (params?: GetResellersProductsFilters) => { + const handleGetResellersProducts = async ({ signal }: { signal: AbortSignal }) => { const { data } = await axios.get(`${API_ENDPOINTS.resellers_products.get_all}`, { params: { - sort: params?.sort, - in_stock: params?.in_stock, - search: params?.search, - has_discount: params?.has_discount, - category: params?.category, - price_gte: params?.price_gte, - price_lte: params?.price_lte, - offset: Number(params?.page) * 15 - 15, + sort: sort.value || "newest", + in_stock: in_stock.value, + search: searchDebounced.value, + has_discount: has_discount.value, + category: products_category.value, + price_gte: price_gte.value, + price_lte: price_lte.value, + offset: Number(page.value) * 15 - 15, limit: 15, }, + signal, }); return data; @@ -47,8 +88,18 @@ const useGetResellersProducts = (params?: ComputedRef handleGetResellersProducts(params?.value), + queryKey: [ + QUERY_KEYS.resellers_products, + searchDebounced, + sort, + in_stock, + has_discount, + products_category, + price_gte, + price_lte, + page, + ], + queryFn: ({ signal }) => handleGetResellersProducts({ signal }), }); }; diff --git a/frontend/composables/api/tickets/useGetAllTickets.ts b/frontend/composables/api/tickets/useGetAllTickets.ts index 1ef9e67..6ab5d79 100644 --- a/frontend/composables/api/tickets/useGetAllTickets.ts +++ b/frontend/composables/api/tickets/useGetAllTickets.ts @@ -1,6 +1,7 @@ // imports import { useQuery } from "@tanstack/vue-query"; +import { useAppParams } from "~/composables/global/useAppParams"; import { API_ENDPOINTS, QUERY_KEYS } from "~/constants"; // types @@ -13,19 +14,21 @@ export type GetAllTicketsRequest = { page: string | string[]; }; -const useGetAllTickets = (params: ComputedRef) => { +const useGetAllTickets = () => { // state const { $axios: axios } = useNuxtApp(); + const { sort, status, page } = useAppParams(); + // methods - const handleGetAllTickets = async (params: GetAllTicketsRequest) => { + const handleGetAllTickets = async () => { const { data } = await axios.get(API_ENDPOINTS.tickets.get_all, { params: { - sort: params.sort, - filter: params.status, - offset: Number(params.page) * 7 - 7, + sort: sort.value ?? "created_at", + filter: status.value, + offset: Number(page.value) * 7 - 7, limit: 7, }, }); @@ -33,8 +36,8 @@ const useGetAllTickets = (params: ComputedRef) => { }; return useQuery({ - queryKey: [QUERY_KEYS.tickets, params], - queryFn: () => handleGetAllTickets(params.value), + queryKey: [QUERY_KEYS.tickets, sort, status, page], + queryFn: () => handleGetAllTickets(), }); }; diff --git a/frontend/composables/global/useAppParams.ts b/frontend/composables/global/useAppParams.ts new file mode 100644 index 0000000..7469317 --- /dev/null +++ b/frontend/composables/global/useAppParams.ts @@ -0,0 +1,71 @@ +import { PRODUCT_RANGE } from "~/constants"; + +export const useAppParams = () => { + // state + + const { y } = useWindowScroll({ behavior: "smooth" }); + + const slug = useRouteParams("slug"); + + const sort = useRouteQuery("sort", undefined, { + mode: "replace", + }); + + const search = useRouteQuery("search", "", { + mode: "replace", + }); + + const page = useRouteQuery("page", 1, { + mode: "push", + transform: (value) => (!!value ? +value : undefined), + }); + + const category = useRouteQuery("category", "", { + mode: "replace", + }); + + const status = useRouteQuery("status", undefined, { + mode: "replace", + }); + + const price_gte = useRouteQuery("price_gte", PRODUCT_RANGE.min, { + mode: "replace", + }); + + const price_lte = useRouteQuery("price_lte", PRODUCT_RANGE.max, { + mode: "replace", + }); + + const in_stock = useRouteQuery("in_stock", "false", { + mode: "replace", + }); + + const has_discount = useRouteQuery("has_discount", "false", { + mode: "replace", + }); + + const tracking_code = useRouteQuery("tracking_code", "", { + mode: "replace", + }); + + watch( + () => page.value, + () => { + y.value = 0; + } + ); + + return { + slug, + sort, + search, + page, + category, + price_gte, + price_lte, + in_stock, + status, + has_discount, + tracking_code, + }; +};