feat: deals fetch

This commit is contained in:
2025-08-03 16:55:36 +04:00
parent 5435750fb5
commit 315e7db3db
14 changed files with 148 additions and 71 deletions

View File

@ -1,5 +1,5 @@
import { Card } from "@mantine/core"; import { Card } from "@mantine/core";
import { DealSchema } from "@/types/DealSchema"; import { DealSchema } from "@/client";
type Props = { type Props = {
deal: DealSchema; deal: DealSchema;

View File

@ -1,8 +1,9 @@
import React, { FC, useMemo } from "react"; import React, { FC, useMemo } from "react";
import { Box } from "@mantine/core"; import { Box } from "@mantine/core";
import DealCard from "@/app/deals/components/DealCard/DealCard"; import DealCard from "@/app/deals/components/DealCard/DealCard";
import { DealSchema } from "@/client";
import { SortableItem } from "@/components/SortableDnd/SortableItem"; import { SortableItem } from "@/components/SortableDnd/SortableItem";
import { DealSchema } from "@/types/DealSchema";
type Props = { type Props = {
deal: DealSchema; deal: DealSchema;

View File

@ -3,8 +3,7 @@ import { defaultDropAnimation, DragOverlay } from "@dnd-kit/core";
import DealCard from "@/app/deals/components/DealCard/DealCard"; import DealCard from "@/app/deals/components/DealCard/DealCard";
import StatusColumn from "@/app/deals/components/StatusColumn/StatusColumn"; import StatusColumn from "@/app/deals/components/StatusColumn/StatusColumn";
import { useStatusesContext } from "@/app/deals/contexts/StatusesContext"; import { useStatusesContext } from "@/app/deals/contexts/StatusesContext";
import { DealSchema } from "@/types/DealSchema"; import { DealSchema, StatusSchema } from "@/client";
import { StatusSchema } from "@/client";
type Props = { type Props = {
activeDeal: DealSchema | null; activeDeal: DealSchema | null;

View File

@ -6,8 +6,7 @@ import {
} from "@dnd-kit/sortable"; } from "@dnd-kit/sortable";
import { Box, Stack, Text } from "@mantine/core"; import { Box, Stack, Text } from "@mantine/core";
import DealContainer from "@/app/deals/components/DealContainer/DealContainer"; import DealContainer from "@/app/deals/components/DealContainer/DealContainer";
import { StatusSchema } from "@/client"; import { DealSchema, StatusSchema } from "@/client";
import { DealSchema } from "@/types/DealSchema";
import { sortByLexorank } from "@/utils/lexorank"; import { sortByLexorank } from "@/utils/lexorank";
type Props = { type Props = {

View File

@ -8,9 +8,8 @@ import React, {
useState, useState,
} from "react"; } from "react";
import { useBoardsContext } from "@/app/deals/contexts/BoardsContext"; import { useBoardsContext } from "@/app/deals/contexts/BoardsContext";
import useDeals from "@/app/deals/hooks/useDeals"; import { DealSchema, StatusSchema } from "@/client";
import { StatusSchema } from "@/client"; import useDealsList from "@/hooks/useDealsList";
import { DealSchema } from "@/types/DealSchema";
type StatusesContextState = { type StatusesContextState = {
statuses: StatusSchema[]; statuses: StatusSchema[];
@ -25,8 +24,8 @@ const StatusesContext = createContext<StatusesContextState | undefined>(
const useStatusesContextState = () => { const useStatusesContextState = () => {
const [statuses, setStatuses] = useState<StatusSchema[]>([]); const [statuses, setStatuses] = useState<StatusSchema[]>([]);
const { deals, setDeals } = useDeals();
const { selectedBoard } = useBoardsContext(); const { selectedBoard } = useBoardsContext();
const { deals, setDeals } = useDealsList({ boardId: selectedBoard?.id });
useEffect(() => { useEffect(() => {
setStatuses(selectedBoard?.statuses ?? []); setStatuses(selectedBoard?.statuses ?? []);

View File

@ -1,13 +0,0 @@
import { useState } from "react";
import { BoardSchema } from "@/client";
const useBoards = () => {
const [boards, setBoards] = useState<BoardSchema[]>([]);
return {
boards,
setBoards,
};
};
export default useBoards;

View File

@ -1,37 +0,0 @@
import { useEffect, useState } from "react";
import { DealSchema } from "@/types/DealSchema";
const useDeals = () => {
const [deals, setDeals] = useState<DealSchema[]>([]);
useEffect(() => {
const INITIAL_DEALS: DealSchema[] = [
{
id: 1,
name: "Deal 1",
lexorank: "0|gggggg:",
statusId: 1,
},
{
id: 2,
name: "Deal 2",
lexorank: "0|mmmmmm:",
statusId: 1,
},
{
id: 3,
name: "Deal 3",
lexorank: "0|ssssss:",
statusId: 2,
},
];
setDeals(INITIAL_DEALS);
}, []);
return {
deals,
setDeals,
};
};
export default useDeals;

View File

@ -4,8 +4,7 @@ import { throttle } from "lodash";
import { useStatusesContext } from "@/app/deals/contexts/StatusesContext"; import { useStatusesContext } from "@/app/deals/contexts/StatusesContext";
import useGetNewRank from "@/app/deals/hooks/useGetNewRank"; import useGetNewRank from "@/app/deals/hooks/useGetNewRank";
import { getStatusId, isStatusId } from "@/app/deals/utils/statusId"; import { getStatusId, isStatusId } from "@/app/deals/utils/statusId";
import { StatusSchema } from "@/client"; import { DealSchema, StatusSchema } from "@/client";
import { DealSchema } from "@/types/DealSchema";
import { sortByLexorank } from "@/utils/lexorank"; import { sortByLexorank } from "@/utils/lexorank";
type Props = { type Props = {

View File

@ -1,6 +1,6 @@
import { LexoRank } from "lexorank"; import { LexoRank } from "lexorank";
import { useStatusesContext } from "@/app/deals/contexts/StatusesContext"; import { useStatusesContext } from "@/app/deals/contexts/StatusesContext";
import { DealSchema } from "@/types/DealSchema"; import { DealSchema } from "@/client";
import { getNewLexorank, sortByLexorank } from "@/utils/lexorank"; import { getNewLexorank, sortByLexorank } from "@/utils/lexorank";
const useGetNewRank = () => { const useGetNewRank = () => {

View File

@ -2,8 +2,12 @@
import { queryOptions } from "@tanstack/react-query"; import { queryOptions } from "@tanstack/react-query";
import { client as _heyApiClient } from "../client.gen"; import { client as _heyApiClient } from "../client.gen";
import { getBoards, getProjects, type Options } from "../sdk.gen"; import { getBoards, getDeals, getProjects, type Options } from "../sdk.gen";
import type { GetBoardsData, GetProjectsData } from "../types.gen"; import type {
GetBoardsData,
GetDealsData,
GetProjectsData,
} from "../types.gen";
export type QueryKey<TOptions extends Options> = [ export type QueryKey<TOptions extends Options> = [
Pick<TOptions, "baseURL" | "body" | "headers" | "path" | "query"> & { Pick<TOptions, "baseURL" | "body" | "headers" | "path" | "query"> & {
@ -82,3 +86,24 @@ export const getBoardsOptions = (options: Options<GetBoardsData>) => {
queryKey: getBoardsQueryKey(options), queryKey: getBoardsQueryKey(options),
}); });
}; };
export const getDealsQueryKey = (options: Options<GetDealsData>) =>
createQueryKey("getDeals", options);
/**
* Get Deals
*/
export const getDealsOptions = (options: Options<GetDealsData>) => {
return queryOptions({
queryFn: async ({ queryKey, signal }) => {
const { data } = await getDeals({
...options,
...queryKey[0],
signal,
throwOnError: true,
});
return data;
},
queryKey: getDealsQueryKey(options),
});
};

View File

@ -6,6 +6,9 @@ import type {
GetBoardsData, GetBoardsData,
GetBoardsErrors, GetBoardsErrors,
GetBoardsResponses, GetBoardsResponses,
GetDealsData,
GetDealsErrors,
GetDealsResponses,
GetProjectsData, GetProjectsData,
GetProjectsResponses, GetProjectsResponses,
} from "./types.gen"; } from "./types.gen";
@ -60,3 +63,20 @@ export const getBoards = <ThrowOnError extends boolean = false>(
...options, ...options,
}); });
}; };
/**
* Get Deals
*/
export const getDeals = <ThrowOnError extends boolean = false>(
options: Options<GetDealsData, ThrowOnError>
) => {
return (options.client ?? _heyApiClient).get<
GetDealsResponses,
GetDealsErrors,
ThrowOnError
>({
responseType: "json",
url: "/deal/{board_id}",
...options,
});
};

View File

@ -22,6 +22,28 @@ export type BoardSchema = {
statuses: Array<StatusSchema>; statuses: Array<StatusSchema>;
}; };
/**
* DealSchema
*/
export type DealSchema = {
/**
* Name
*/
name: string;
/**
* Id
*/
id: number;
/**
* Lexorank
*/
lexorank: string;
/**
* Statusid
*/
statusId: number;
};
/** /**
* GetBoardsResponse * GetBoardsResponse
*/ */
@ -32,6 +54,16 @@ export type GetBoardsResponse = {
boards: Array<BoardSchema>; boards: Array<BoardSchema>;
}; };
/**
* GetDealsResponse
*/
export type GetDealsResponse = {
/**
* Deals
*/
deals: Array<DealSchema>;
};
/** /**
* GetProjectsResponse * GetProjectsResponse
*/ */
@ -149,6 +181,36 @@ export type GetBoardsResponses = {
export type GetBoardsResponse2 = GetBoardsResponses[keyof GetBoardsResponses]; export type GetBoardsResponse2 = GetBoardsResponses[keyof GetBoardsResponses];
export type GetDealsData = {
body?: never;
path: {
/**
* Board Id
*/
board_id: number;
};
query?: never;
url: "/deal/{board_id}";
};
export type GetDealsErrors = {
/**
* Validation Error
*/
422: HttpValidationError;
};
export type GetDealsError = GetDealsErrors[keyof GetDealsErrors];
export type GetDealsResponses = {
/**
* Successful Response
*/
200: GetDealsResponse;
};
export type GetDealsResponse2 = GetDealsResponses[keyof GetDealsResponses];
export type ClientOptions = { export type ClientOptions = {
baseURL: "http://localhost:8000" | (string & {}); baseURL: "http://localhost:8000" | (string & {});
}; };

29
src/hooks/useDealsList.ts Normal file
View File

@ -0,0 +1,29 @@
import { useEffect, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { DealSchema } from "@/client";
import { getDealsOptions } from "@/client/@tanstack/react-query.gen";
type Props = {
boardId?: number;
};
const useDealsList = ({ boardId }: Props) => {
const [deals, setDeals] = useState<DealSchema[]>([]);
const { data, refetch, isLoading } = useQuery({
...getDealsOptions({ path: { board_id: boardId! } }),
enabled: boardId !== undefined,
});
useEffect(() => {
if (boardId === undefined) {
setDeals([]);
} else if (data?.deals) {
setDeals(data.deals);
}
}, [data?.deals, boardId]);
return { deals, setDeals, refetch, isLoading };
};
export default useDealsList;

View File

@ -1,6 +0,0 @@
export type DealSchema = {
id: number;
name: string;
lexorank: string;
statusId: number;
};