ENCOA-315: Small fix and merge

This commit is contained in:
Carlos-Mesquita
2025-01-22 05:24:49 +00:00
18 changed files with 1857 additions and 1044 deletions

View File

@@ -3,13 +3,13 @@ import { useEffect, useState } from "react";
const endpoints: Record<string, string> = {
stats: "/api/stats",
training: "/api/training"
training: "/api/training",
};
export default function useFilterRecordsByUser<T extends any[]>(
id?: string,
shouldNotQuery?: boolean,
recordType: string = 'stats'
recordType: string = "stats"
) {
type ElementType = T extends (infer U)[] ? U : never;
@@ -19,7 +19,7 @@ export default function useFilterRecordsByUser<T extends any[]>(
const endpointURL = endpoints[recordType] || endpoints.stats;
// CAUTION: This makes the assumption that the record enpoint has a /user/${id} endpoint
const endpoint = !id ? endpointURL: `${endpointURL}/user/${id}`;
const endpoint = !id ? endpointURL : `${endpointURL}/user/${id}`;
const getData = () => {
if (shouldNotQuery) return;
@@ -31,7 +31,7 @@ export default function useFilterRecordsByUser<T extends any[]>(
.get<T>(endpoint)
.then((response) => {
// CAUTION: This makes the assumption ElementType has a "user" field that contains the user id
setData(response.data.filter((x: ElementType) => (id ? (x as any).user === id : true)) as T);
setData(response.data);
})
.catch(() => setIsError(true))
.finally(() => setIsLoading(false));
@@ -42,10 +42,10 @@ export default function useFilterRecordsByUser<T extends any[]>(
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [id, shouldNotQuery, recordType, endpoint]);
return {
data,
reload: getData,
isLoading,
isError
return {
data,
reload: getData,
isLoading,
isError,
};
}
}

View File

@@ -17,8 +17,7 @@ export default function usePermissions(user: string) {
.get<Permission[]>(`/api/permissions`)
.then((response) => {
const permissionTypes = response.data
.filter((x) => !x.users.includes(user))
.reduce((acc, curr) => [...acc, curr.type], [] as PermissionType[]);
.reduce((acc, curr) => curr.users.includes(user)? acc : [...acc, curr.type], [] as PermissionType[]);
setPermissions(permissionTypes);
})
.finally(() => setIsLoading(false));

View File

@@ -1,22 +1,28 @@
import React from "react";
import useTickets from "./useTickets";
import { useState, useEffect } from "react";
import axios from "axios";
const useTicketsListener = (userId?: string) => {
const { tickets, reload } = useTickets();
const [assignedTickets, setAssignedTickets] = useState([]);
React.useEffect(() => {
const getData = () => {
axios
.get("/api/tickets/assignedToUser")
.then((response) => setAssignedTickets(response.data));
};
useEffect(() => {
getData();
}, []);
useEffect(() => {
const intervalId = setInterval(() => {
reload();
getData();
}, 60 * 1000);
return () => clearInterval(intervalId);
}, [reload]);
}, [assignedTickets]);
if (userId) {
const assignedTickets = tickets.filter(
(ticket) => ticket.assignedTo === userId && ticket.status === "submitted"
);
return {
assignedTickets,
totalAssignedTickets: assignedTickets.length,

27
src/hooks/useUserData.tsx Normal file
View File

@@ -0,0 +1,27 @@
import { useEffect, useState, useCallback } from "react";
import { User } from "../interfaces/user";
import axios from "axios";
export default function useUserData({
userId,
}: {
userId: string;
}) {
const [userData, setUserData] = useState<User | undefined>(undefined);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
const getData = useCallback(() => {
if (!userId ) return;
setIsLoading(true);
axios
.get(`/api/users/${userId}`)
.then((response) => setUserData(response.data))
.finally(() => setIsLoading(false))
.catch((error) => setIsError(true));
}, [userId]);
useEffect(getData, [getData]);
return { userData, isLoading, isError, reload: getData };
}

View File

@@ -0,0 +1,99 @@
import Axios from "axios";
import { useCallback, useEffect, useState } from "react";
import { setupCache } from "axios-cache-interceptor";
import Option from "../interfaces/option";
const instance = Axios.create();
const axios = setupCache(instance);
export default function useUsersSelect(props?: {
type?: string;
size?: number;
orderBy?: string;
direction?: "asc" | "desc";
entities?: string[] | string;
}) {
const [inputValue, setInputValue] = useState("");
const [users, setUsers] = useState<Option[]>([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(0);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
const onScrollLoadMoreOptions = useCallback(() => {
if (users.length === total) return;
const params = new URLSearchParams();
if (!!props)
Object.keys(props).forEach((key) => {
if (props[key as keyof typeof props] !== undefined)
params.append(key, props[key as keyof typeof props]!.toString());
});
setIsLoading(true);
return axios
.get<{ users: Option[]; total: number }>(
`/api/users/search?value=${inputValue}&page=${
page + 1
}&${params.toString()}`,
{ headers: { page: "register" } }
)
.then((response) => {
setPage((curr) => curr + 1);
setTotal(response.data.total);
setUsers((curr) => [...curr, ...response.data.users]);
setIsLoading(false);
return response.data.users;
});
}, [inputValue, page, props, total, users.length]);
const loadOptions = useCallback(
async (inputValue: string,forced?:boolean) => {
let load = true;
setInputValue((currValue) => {
if (!forced&&currValue === inputValue) {
load = false;
return currValue;
}
return inputValue;
});
if (!load) return;
const params = new URLSearchParams();
if (!!props)
Object.keys(props).forEach((key) => {
if (props[key as keyof typeof props] !== undefined)
params.append(key, props[key as keyof typeof props]!.toString());
});
setIsLoading(true);
setPage(0);
return axios
.get<{ users: Option[]; total: number }>(
`/api/users/search?value=${inputValue}&page=0&${params.toString()}`,
{ headers: { page: "register" } }
)
.then((response) => {
setTotal(response.data.total);
setUsers(response.data.users);
setIsLoading(false);
return response.data.users;
});
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[props?.entities, props?.type, props?.size, props?.orderBy, props?.direction]
);
useEffect(() => {
loadOptions("",true);
}, [loadOptions]);
return {
users,
total,
isLoading,
isError,
onScrollLoadMoreOptions,
loadOptions,
inputValue,
};
}