style: run prettier on entire codebase
This commit is contained in:
@@ -1,45 +1,48 @@
|
||||
import { useCallback, useRef } from 'react'
|
||||
import { useAlert } from '../context/AlertContext'
|
||||
import apiFetch from '../utils/api'
|
||||
import { useCallback, useRef } from "react";
|
||||
import { useAlert } from "../context/AlertContext";
|
||||
import apiFetch from "../utils/api";
|
||||
|
||||
interface ApiCallResult<T> {
|
||||
data: T | null
|
||||
ok: boolean
|
||||
response: Response | null
|
||||
data: T | null;
|
||||
ok: boolean;
|
||||
response: Response | null;
|
||||
}
|
||||
|
||||
export default function useApiCall() {
|
||||
const alert = useAlert()
|
||||
const abortRef = useRef<AbortController | null>(null)
|
||||
const alert = useAlert();
|
||||
const abortRef = useRef<AbortController | null>(null);
|
||||
|
||||
const call = useCallback(async <T = unknown>(
|
||||
url: string,
|
||||
options: RequestInit = {},
|
||||
errorMsg = 'Chyba při načítání dat'
|
||||
): Promise<ApiCallResult<T>> => {
|
||||
if (abortRef.current) abortRef.current.abort()
|
||||
const controller = new AbortController()
|
||||
abortRef.current = controller
|
||||
const call = useCallback(
|
||||
async <T = unknown>(
|
||||
url: string,
|
||||
options: RequestInit = {},
|
||||
errorMsg = "Chyba při načítání dat",
|
||||
): Promise<ApiCallResult<T>> => {
|
||||
if (abortRef.current) abortRef.current.abort();
|
||||
const controller = new AbortController();
|
||||
abortRef.current = controller;
|
||||
|
||||
try {
|
||||
const response = await apiFetch(url, {
|
||||
...options,
|
||||
signal: controller.signal,
|
||||
})
|
||||
const data = await response.json()
|
||||
if (!response.ok || !data.success) {
|
||||
alert.error(data.error || errorMsg)
|
||||
return { data: null, ok: false, response }
|
||||
try {
|
||||
const response = await apiFetch(url, {
|
||||
...options,
|
||||
signal: controller.signal,
|
||||
});
|
||||
const data = await response.json();
|
||||
if (!response.ok || !data.success) {
|
||||
alert.error(data.error || errorMsg);
|
||||
return { data: null, ok: false, response };
|
||||
}
|
||||
return { data: data.data as T, ok: true, response };
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof Error && err.name === "AbortError") {
|
||||
return { data: null, ok: false, response: null };
|
||||
}
|
||||
alert.error(errorMsg);
|
||||
return { data: null, ok: false, response: null };
|
||||
}
|
||||
return { data: data.data as T, ok: true, response }
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof Error && err.name === 'AbortError') {
|
||||
return { data: null, ok: false, response: null }
|
||||
}
|
||||
alert.error(errorMsg)
|
||||
return { data: null, ok: false, response: null }
|
||||
}
|
||||
}, [alert])
|
||||
},
|
||||
[alert],
|
||||
);
|
||||
|
||||
return { call }
|
||||
return { call };
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,14 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
export default function useDebounce<T>(value: T, delay: number): T {
|
||||
const [debouncedValue, setDebouncedValue] = useState<T>(value)
|
||||
const [debouncedValue, setDebouncedValue] = useState<T>(value);
|
||||
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedValue(value)
|
||||
}, delay)
|
||||
return () => clearTimeout(handler)
|
||||
}, [value, delay])
|
||||
setDebouncedValue(value);
|
||||
}, delay);
|
||||
return () => clearTimeout(handler);
|
||||
}, [value, delay]);
|
||||
|
||||
return debouncedValue
|
||||
return debouncedValue;
|
||||
}
|
||||
|
||||
@@ -1,90 +1,126 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { useAlert } from '../context/AlertContext'
|
||||
import apiFetch from '../utils/api'
|
||||
import useDebounce from './useDebounce'
|
||||
import { useState, useEffect, useCallback, useRef } from "react";
|
||||
import { useAlert } from "../context/AlertContext";
|
||||
import apiFetch from "../utils/api";
|
||||
import useDebounce from "./useDebounce";
|
||||
|
||||
const API_BASE = '/api/admin'
|
||||
const API_BASE = "/api/admin";
|
||||
|
||||
interface PaginationData {
|
||||
total: number
|
||||
page: number
|
||||
per_page: number
|
||||
total_pages: number
|
||||
total: number;
|
||||
page: number;
|
||||
per_page: number;
|
||||
total_pages: number;
|
||||
}
|
||||
|
||||
interface UseListDataOptions {
|
||||
dataKey?: string
|
||||
search?: string
|
||||
sort?: string
|
||||
order?: string
|
||||
page?: number
|
||||
perPage?: number
|
||||
extraParams?: Record<string, string>
|
||||
errorMsg?: string
|
||||
dataKey?: string;
|
||||
search?: string;
|
||||
sort?: string;
|
||||
order?: string;
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
extraParams?: Record<string, string>;
|
||||
errorMsg?: string;
|
||||
}
|
||||
|
||||
export default function useListData<T = unknown>(
|
||||
endpoint: string,
|
||||
options: UseListDataOptions = {}
|
||||
options: UseListDataOptions = {},
|
||||
) {
|
||||
const { dataKey, search = '', sort, order, page = 1, perPage = 25, extraParams = {}, errorMsg = 'Nepodařilo se načíst data' } = options
|
||||
const alert = useAlert()
|
||||
const [items, setItems] = useState<T[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [initialLoad, setInitialLoad] = useState(true)
|
||||
const [pagination, setPagination] = useState<PaginationData | null>(null)
|
||||
const abortRef = useRef<AbortController | null>(null)
|
||||
const debouncedSearch = useDebounce(search, 300)
|
||||
const {
|
||||
dataKey,
|
||||
search = "",
|
||||
sort,
|
||||
order,
|
||||
page = 1,
|
||||
perPage = 25,
|
||||
extraParams = {},
|
||||
errorMsg = "Nepodařilo se načíst data",
|
||||
} = options;
|
||||
const alert = useAlert();
|
||||
const [items, setItems] = useState<T[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [initialLoad, setInitialLoad] = useState(true);
|
||||
const [pagination, setPagination] = useState<PaginationData | null>(null);
|
||||
const abortRef = useRef<AbortController | null>(null);
|
||||
const debouncedSearch = useDebounce(search, 300);
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
if (abortRef.current) abortRef.current.abort()
|
||||
const controller = new AbortController()
|
||||
abortRef.current = controller
|
||||
if (abortRef.current) abortRef.current.abort();
|
||||
const controller = new AbortController();
|
||||
abortRef.current = controller;
|
||||
|
||||
try {
|
||||
const params = new URLSearchParams({
|
||||
page: String(page),
|
||||
per_page: String(perPage),
|
||||
})
|
||||
if (debouncedSearch) params.set('search', debouncedSearch)
|
||||
if (sort) params.set('sort', sort)
|
||||
if (order) params.set('order', order)
|
||||
});
|
||||
if (debouncedSearch) params.set("search", debouncedSearch);
|
||||
if (sort) params.set("sort", sort);
|
||||
if (order) params.set("order", order);
|
||||
Object.entries(extraParams).forEach(([k, v]) => {
|
||||
if (v) params.set(k, v)
|
||||
})
|
||||
if (v) params.set(k, v);
|
||||
});
|
||||
|
||||
const url = endpoint.startsWith('/') ? `${endpoint}?${params}` : `${API_BASE}/${endpoint}?${params}`
|
||||
const response = await apiFetch(url, { signal: controller.signal })
|
||||
if (response.status === 401) return
|
||||
const result = await response.json()
|
||||
const url = endpoint.startsWith("/")
|
||||
? `${endpoint}?${params}`
|
||||
: `${API_BASE}/${endpoint}?${params}`;
|
||||
const response = await apiFetch(url, { signal: controller.signal });
|
||||
if (response.status === 401) return;
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
const data = dataKey ? result.data[dataKey] : (Array.isArray(result.data) ? result.data : result.data?.items || [])
|
||||
setItems(data || [])
|
||||
const pag = result.pagination || (!Array.isArray(result.data) && result.data?.pagination) || null
|
||||
setPagination(pag || {
|
||||
total: data?.length ?? 0,
|
||||
page,
|
||||
per_page: perPage,
|
||||
total_pages: 1,
|
||||
})
|
||||
const data = dataKey
|
||||
? result.data[dataKey]
|
||||
: Array.isArray(result.data)
|
||||
? result.data
|
||||
: result.data?.items || [];
|
||||
setItems(data || []);
|
||||
const pag =
|
||||
result.pagination ||
|
||||
(!Array.isArray(result.data) && result.data?.pagination) ||
|
||||
null;
|
||||
setPagination(
|
||||
pag || {
|
||||
total: data?.length ?? 0,
|
||||
page,
|
||||
per_page: perPage,
|
||||
total_pages: 1,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
alert.error(result.error || errorMsg)
|
||||
alert.error(result.error || errorMsg);
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof Error && err.name === 'AbortError') return
|
||||
alert.error(errorMsg)
|
||||
if (err instanceof Error && err.name === "AbortError") return;
|
||||
alert.error(errorMsg);
|
||||
} finally {
|
||||
setLoading(false)
|
||||
setInitialLoad(false)
|
||||
setLoading(false);
|
||||
setInitialLoad(false);
|
||||
}
|
||||
}, [endpoint, debouncedSearch, sort, order, page, perPage, dataKey, JSON.stringify(extraParams)]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
endpoint,
|
||||
debouncedSearch,
|
||||
sort,
|
||||
order,
|
||||
page,
|
||||
perPage,
|
||||
dataKey,
|
||||
JSON.stringify(extraParams),
|
||||
]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
useEffect(() => {
|
||||
fetchData()
|
||||
fetchData();
|
||||
return () => {
|
||||
if (abortRef.current) abortRef.current.abort()
|
||||
}
|
||||
}, [fetchData])
|
||||
if (abortRef.current) abortRef.current.abort();
|
||||
};
|
||||
}, [fetchData]);
|
||||
|
||||
return { items, setItems, loading, initialLoad, pagination, refetch: fetchData }
|
||||
return {
|
||||
items,
|
||||
setItems,
|
||||
loading,
|
||||
initialLoad,
|
||||
pagination,
|
||||
refetch: fetchData,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function useModalLock(isOpen: boolean): void {
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
document.body.style.overflow = 'hidden'
|
||||
document.body.style.overflow = "hidden";
|
||||
} else {
|
||||
document.body.style.overflow = ''
|
||||
document.body.style.overflow = "";
|
||||
}
|
||||
return () => {
|
||||
document.body.style.overflow = ''
|
||||
}
|
||||
}, [isOpen])
|
||||
document.body.style.overflow = "";
|
||||
};
|
||||
}, [isOpen]);
|
||||
}
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
import { useState, useCallback, useRef } from 'react'
|
||||
import { useState, useCallback, useRef } from "react";
|
||||
|
||||
interface SortState {
|
||||
sort: string
|
||||
order: 'asc' | 'desc'
|
||||
sort: string;
|
||||
order: "asc" | "desc";
|
||||
}
|
||||
|
||||
export default function useTableSort(defaultSort = 'id', defaultOrder: 'asc' | 'desc' = 'desc') {
|
||||
const [state, setState] = useState<SortState>({ sort: defaultSort, order: defaultOrder })
|
||||
const userClicked = useRef(false)
|
||||
export default function useTableSort(
|
||||
defaultSort = "id",
|
||||
defaultOrder: "asc" | "desc" = "desc",
|
||||
) {
|
||||
const [state, setState] = useState<SortState>({
|
||||
sort: defaultSort,
|
||||
order: defaultOrder,
|
||||
});
|
||||
const userClicked = useRef(false);
|
||||
|
||||
const handleSort = useCallback((column: string) => {
|
||||
userClicked.current = true
|
||||
setState(prev => {
|
||||
userClicked.current = true;
|
||||
setState((prev) => {
|
||||
if (prev.sort === column) {
|
||||
return { sort: column, order: prev.order === 'asc' ? 'desc' : 'asc' }
|
||||
return { sort: column, order: prev.order === "asc" ? "desc" : "asc" };
|
||||
}
|
||||
return { sort: column, order: 'desc' }
|
||||
})
|
||||
}, [])
|
||||
return { sort: column, order: "desc" };
|
||||
});
|
||||
}, []);
|
||||
|
||||
const activeSort = userClicked.current ? state.sort : null
|
||||
const activeSort = userClicked.current ? state.sort : null;
|
||||
|
||||
return { sort: state.sort, order: state.order, handleSort, activeSort }
|
||||
return { sort: state.sort, order: state.order, handleSort, activeSort };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user