diff --git a/src/app/(gistLayout)/mygist/page-ui.tsx b/src/app/(gistLayout)/mygist/page-ui.tsx
index 7dbf497..bc65ef9 100644
--- a/src/app/(gistLayout)/mygist/page-ui.tsx
+++ b/src/app/(gistLayout)/mygist/page-ui.tsx
@@ -1,9 +1,12 @@
-import { MyGistListFeature } from '@/components/logic/mygist-list-logic'
-import { SidebarTrigger } from '@/components/shadcn/sidebar'
-import MenuButton from '@/components/ui/menu-button'
-import { PaginationComponent } from '@/components/ui/pagination'
-import TooltipShortcut, { TooltipShortcutTrigger } from '@/components/ui/tooltip-shortcut'
-import { TornadoIcon } from 'lucide-react'
+import { PaginationProvider } from "@/components/contexts/pagination";
+import { MyGistListFeature } from "@/components/logic/mygist-list-logic";
+import { SidebarTrigger } from "@/components/shadcn/sidebar";
+import MenuButton from "@/components/ui/menu-button";
+import { PaginationComponent } from "@/components/ui/pagination";
+import TooltipShortcut, {
+ TooltipShortcutTrigger,
+} from "@/components/ui/tooltip-shortcut";
+import { TornadoIcon } from "lucide-react";
interface MyGistPageProps {}
@@ -12,24 +15,30 @@ export default function MyGistsPage({}: MyGistPageProps) {
-
+
- } variant={'menu'}>
+ }
+ variant={"menu"}
+ >
Sort by
+
-
-
-
+
+
+
+
+
- )
+ );
}
diff --git a/src/components/contexts/pagination.tsx b/src/components/contexts/pagination.tsx
new file mode 100644
index 0000000..20166cf
--- /dev/null
+++ b/src/components/contexts/pagination.tsx
@@ -0,0 +1,95 @@
+"use client";
+import { usePathname, useRouter, useSearchParams } from "next/navigation";
+import {
+ createContext,
+ ReactNode,
+ useCallback,
+ useEffect,
+ useState,
+} from "react";
+
+interface PaginationContextContent {
+ offset: number;
+ limit: number;
+ nb_pages?: number;
+ setOffset: (offset: number) => void;
+ setLimit: (limit: number) => void;
+ setNbPages: (nb_pages: number) => void;
+}
+
+const PaginationInitialState = {
+ offset: 0,
+ limit: 9,
+ nb_pages: 0,
+ setOffset: (offset: number) => {},
+ setLimit: (limit: number) => {},
+ setNbPages: (nb_pages: number) => {},
+};
+
+export const PaginationContext = createContext(
+ PaginationInitialState,
+);
+
+export function PaginationProvider({
+ children,
+ fromUrl,
+}: {
+ children: ReactNode;
+ fromUrl: boolean;
+}) {
+ const [offset, setOffset] = useState(PaginationInitialState.offset);
+ const [limit, setLimit] = useState(PaginationInitialState.limit);
+ const [nb_pages, setNbPages] = useState(PaginationInitialState.nb_pages);
+ const searchParams = useSearchParams();
+ const pathname = usePathname();
+ const router = useRouter();
+
+ const checkOffset = useCallback(
+ (offset: number) => {
+ if (offset >= 0 && offset <= nb_pages * limit) {
+ return true;
+ }
+ return false;
+ },
+ [nb_pages, limit],
+ );
+
+ const setOffsetHandler = useCallback(
+ (offset: number) => {
+ if (checkOffset(offset)) {
+ if (fromUrl) {
+ const page = Math.floor(offset / limit) + 1;
+ router.push(`${pathname}?page=${page}`);
+ }
+ setOffset(offset);
+ }
+ },
+ [checkOffset, fromUrl, limit, pathname, router],
+ );
+
+ useEffect(() => {
+ if (!fromUrl) return;
+ if (searchParams.has("page")) {
+ const page = parseInt(searchParams.get("page") as string);
+ const offset = (page - 1) * limit;
+ console.log("offset", offset);
+ if (!checkOffset(offset)) return;
+ setOffset(offset);
+ }
+ }, [searchParams, fromUrl, setOffset, limit, setOffsetHandler, checkOffset]);
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/components/logic/mygist-list-logic.tsx b/src/components/logic/mygist-list-logic.tsx
index 1576e26..03871e9 100644
--- a/src/components/logic/mygist-list-logic.tsx
+++ b/src/components/logic/mygist-list-logic.tsx
@@ -1,15 +1,27 @@
"use client";
+import { useContext, useEffect } from "react";
import MyGistList from "../ui/mygist-list";
import { useDeleteGist, useGists } from "@/lib/queries/gists.queries";
+import { PaginationContext } from "../contexts/pagination";
export function MyGistListFeature() {
- const { data } = useGists();
+ const { offset, limit, setNbPages } = useContext(PaginationContext);
+ const { data, nb_pages } = useGists({
+ limit,
+ offset,
+ });
+
+ useEffect(() => {
+ setNbPages(nb_pages || 0);
+ }, [nb_pages, setNbPages]);
+
const { mutate: deleteGist } = useDeleteGist({
onSuccess: (id) => {
console.log(`Deleting gist with ID: ${id}`);
},
});
+
const handleDeleteGist = (id: string) => {
deleteGist(id);
};
diff --git a/src/components/shadcn/button.tsx b/src/components/shadcn/button.tsx
index b6f1a96..48c9cce 100644
--- a/src/components/shadcn/button.tsx
+++ b/src/components/shadcn/button.tsx
@@ -1,48 +1,63 @@
-import * as React from 'react'
-import { Slot } from '@radix-ui/react-slot'
-import { cva, type VariantProps } from 'class-variance-authority'
+import * as React from "react";
+import { Slot } from "@radix-ui/react-slot";
+import { cva, type VariantProps } from "class-variance-authority";
-import { cn } from '@/lib/utils'
+import { cn } from "@/lib/utils";
const buttonVariants = cva(
- 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
- default: 'bg-primary text-primary-foreground hover:bg-primary/90',
- destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
- outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
- secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
- ghost: 'hover:bg-light-background hover:text-foreground',
- link: 'text-primary text-base underline-offset-4 hover:underline',
- icon: 'text-foreground bg-icon hover:bg-icon/80',
- menu: 'text-primary-foreground hover:bg-primary hover:text-primary-foreground',
- header: 'hover:bg-primary hover:text-foreground',
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline:
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-light-background hover:text-foreground",
+ disabled:
+ "hover:bg-light-background hover:text-foreground opacity-50 cursor-not-allowed",
+ link: "text-primary text-base underline-offset-4 hover:underline",
+ icon: "text-foreground bg-icon hover:bg-icon/80",
+ menu: "text-primary-foreground hover:bg-primary hover:text-primary-foreground",
+ header: "hover:bg-primary hover:text-foreground",
},
size: {
- default: 'h-10 px-6 py-3',
- 'no-padding': 'h-10',
- sm: 'h-9 rounded-md px-3',
- lg: 'h-11 rounded-md px-8',
- menu: 'h-10 py-2 px-3',
- icon: 'h-10 w-10',
+ default: "h-10 px-6 py-3",
+ "no-padding": "h-10",
+ sm: "h-9 rounded-md px-3",
+ lg: "h-11 rounded-md px-8",
+ menu: "h-10 py-2 px-3",
+ icon: "h-10 w-10",
},
},
defaultVariants: {
- variant: 'default',
- size: 'default',
+ variant: "default",
+ size: "default",
},
- }
-)
+ },
+);
-export interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps {
- asChild?: boolean
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean;
}
-const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
- const Comp = asChild ? Slot : 'button'
- return
-})
-Button.displayName = 'Button'
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button";
+ return (
+
+ );
+ },
+);
+Button.displayName = "Button";
-export { Button, buttonVariants }
+export { Button, buttonVariants };
diff --git a/src/components/shadcn/pagination.tsx b/src/components/shadcn/pagination.tsx
index 61b8438..1f4c286 100644
--- a/src/components/shadcn/pagination.tsx
+++ b/src/components/shadcn/pagination.tsx
@@ -1,64 +1,120 @@
-import * as React from 'react'
-import { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react'
+import * as React from "react";
+import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
-import { cn } from '@/lib/utils'
-import { ButtonProps, buttonVariants } from './button'
+import { cn } from "@/lib/utils";
+import { ButtonProps, buttonVariants } from "./button";
-const Pagination = ({ className, ...props }: React.ComponentProps<'nav'>) => (
-
-)
-Pagination.displayName = 'Pagination'
+const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
+
+);
+Pagination.displayName = "Pagination";
-const PaginationContent = React.forwardRef>(({ className, ...props }, ref) => (
-
-))
-PaginationContent.displayName = 'PaginationContent'
+const PaginationContent = React.forwardRef<
+ HTMLUListElement,
+ React.ComponentProps<"ul">
+>(({ className, ...props }, ref) => (
+
+));
+PaginationContent.displayName = "PaginationContent";
-const PaginationItem = React.forwardRef>(({ className, ...props }, ref) => )
-PaginationItem.displayName = 'PaginationItem'
+const PaginationItem = React.forwardRef<
+ HTMLLIElement,
+ React.ComponentProps<"li">
+>(({ className, ...props }, ref) => (
+
+));
+PaginationItem.displayName = "PaginationItem";
type PaginationLinkProps = {
- isActive?: boolean
-} & Pick &
- React.ComponentProps<'a'>
+ isActive?: boolean;
+ disabled?: boolean;
+} & Pick &
+ React.ComponentProps<"a">;
-const PaginationLink = ({ className, isActive, size = 'icon', ...props }: PaginationLinkProps) => (
+const PaginationLink = ({
+ className,
+ isActive,
+ disabled,
+ size = "icon",
+ ...props
+}: PaginationLinkProps) => (
-)
-PaginationLink.displayName = 'PaginationLink'
+);
+PaginationLink.displayName = "PaginationLink";
-const PaginationPrevious = ({ className, ...props }: React.ComponentProps) => (
-
+const PaginationPrevious = ({
+ className,
+ ...props
+}: React.ComponentProps) => (
+
Previous
-)
-PaginationPrevious.displayName = 'PaginationPrevious'
+);
+PaginationPrevious.displayName = "PaginationPrevious";
-const PaginationNext = ({ className, ...props }: React.ComponentProps) => (
-
+const PaginationNext = ({
+ className,
+ ...props
+}: React.ComponentProps) => (
+
Next
-)
-PaginationNext.displayName = 'PaginationNext'
+);
+PaginationNext.displayName = "PaginationNext";
-const PaginationEllipsis = ({ className, ...props }: React.ComponentProps<'span'>) => (
-
+const PaginationEllipsis = ({
+ className,
+ ...props
+}: React.ComponentProps<"span">) => (
+
More pages
-)
-PaginationEllipsis.displayName = 'PaginationEllipsis'
+);
+PaginationEllipsis.displayName = "PaginationEllipsis";
-export { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious }
+export {
+ Pagination,
+ PaginationContent,
+ PaginationEllipsis,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious,
+};
diff --git a/src/components/ui/pagination.tsx b/src/components/ui/pagination.tsx
index 56c02f2..2a863f5 100644
--- a/src/components/ui/pagination.tsx
+++ b/src/components/ui/pagination.tsx
@@ -1,31 +1,84 @@
-import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from '../shadcn/pagination'
+"use client";
+import { useCallback, useContext } from "react";
+import { PaginationContext } from "../contexts/pagination";
+import {
+ Pagination,
+ PaginationContent,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious,
+} from "../shadcn/pagination";
export function PaginationComponent() {
+ const { offset, setOffset, limit, nb_pages } = useContext(PaginationContext);
+
+ const current_page = Math.floor(offset / limit) + 1;
+
+ const handleNext = () => {
+ setOffset(offset + limit);
+ };
+
+ const handlePrevious = () => {
+ setOffset(offset - limit);
+ };
+
+ const goToPage = (page: number) => {
+ setOffset((page - 1) * limit);
+ };
+
+ const previousDisabled = useCallback(() => offset === 0, [offset]);
+ const nextDisabled = useCallback(() => {
+ if (nb_pages) {
+ return offset + limit > nb_pages * limit;
+ }
+ return false;
+ }, [offset, nb_pages, limit]);
+
+ if (!nb_pages) {
+ return <>>;
+ }
+
+ if (nb_pages === 0) {
+ return <>>;
+ }
+
return (
-
-
-
- 1
-
-
-
- 2
-
-
-
- 3
-
-
-
+
+ {current_page > 1 && (
+ goToPage(1)}>
+ 1
+
+ )}
+ {nb_pages && nb_pages > 0 && (
+
+
+ {current_page}
+
+
+ )}
+ {current_page <= nb_pages && (
+ goToPage(nb_pages + 1)}>
+ {nb_pages + 1}
+
+ )}
-
+
- )
+ );
}
-export { Pagination }
+export { Pagination };
diff --git a/src/lib/queries/gists.queries.tsx b/src/lib/queries/gists.queries.tsx
index 8d5b5ed..0c2d225 100644
--- a/src/lib/queries/gists.queries.tsx
+++ b/src/lib/queries/gists.queries.tsx
@@ -1,217 +1,257 @@
-'use client'
-import ky from 'ky'
-import { getBackendURL } from '../utils'
-import { Gist } from '@/types'
-import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
+"use client";
+import ky from "ky";
+import { getBackendURL } from "../utils";
+import { Gist } from "@/types";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
//types
export interface ApiGist {
- id: string
- name: string
- content: string
- owner_id: string
- org_id: string | null
+ id: string;
+ name: string;
+ content: string;
+ owner_id: string;
+ org_id: string | null;
+}
+
+export interface GistsWithPaginate {
+ gists: ApiGist[];
+ nb_pages: number;
}
//fetches
-const fetchGists = async () => {
+const fetchGists = async ({
+ offset,
+ limit,
+}: {
+ offset: number;
+ limit: number;
+}): Promise<{
+ gists: Gist[];
+ nb_pages: number;
+}> => {
const json = await ky
- .get(`${getBackendURL()}/gists`, {
- credentials: 'include',
+ .get(`${getBackendURL()}/gists?offset=${offset}&limit=${limit}`, {
+ credentials: "include",
})
- .json()
- return json.map((gist) => {
- return {
- id: gist.id,
- name: gist.name,
- code: gist.content,
- } as Gist
- })
-}
+ .json();
+ return {
+ gists: json.gists.map((gist) => {
+ return {
+ id: gist.id,
+ name: gist.name,
+ code: gist.content,
+ } as Gist;
+ }),
+ nb_pages: json.nb_pages,
+ };
+};
const fetchGist = async (gistId: string): Promise => {
const json = await ky
.get(`${getBackendURL()}/gists/${gistId}`, {
- credentials: 'include',
+ credentials: "include",
})
- .json()
+ .json();
return {
id: json.id,
name: json.name,
code: json.content,
- }
-}
+ };
+};
export interface CreateGistPayload {
- name: string
- content: string
- org_id?: string
+ name: string;
+ content: string;
+ org_id?: string;
}
const fetchCreateGist = async (gist: CreateGistPayload): Promise => {
const json = await ky
.post(`${getBackendURL()}/gists`, {
- credentials: 'include',
+ credentials: "include",
json: gist,
})
- .json()
+ .json();
return {
id: json.id,
name: json.name,
code: json.content,
- }
-}
+ };
+};
export interface PatchGistNamePayload {
- id: string
- name: string
+ id: string;
+ name: string;
}
-const fetchPatchGistName = async (payload: PatchGistNamePayload): Promise => {
+const fetchPatchGistName = async (
+ payload: PatchGistNamePayload,
+): Promise => {
const json = await ky
.patch(`${getBackendURL()}/gists/${payload.id}/name`, {
- credentials: 'include',
+ credentials: "include",
json: { name: payload.name },
})
- .json()
+ .json();
return {
id: json.id,
name: json.name,
code: json.content,
- }
-}
+ };
+};
export interface PatchGistContentPayload {
- id: string
- content: string
+ id: string;
+ content: string;
}
-const fetchPatchGistContent = async (payload: PatchGistContentPayload): Promise => {
+const fetchPatchGistContent = async (
+ payload: PatchGistContentPayload,
+): Promise => {
const json = await ky
.patch(`${getBackendURL()}/gists/${payload.id}/content`, {
- credentials: 'include',
+ credentials: "include",
json: { content: payload.content },
})
- .json()
+ .json();
return {
id: json.id,
name: json.name,
code: json.content,
- }
-}
+ };
+};
const fetchDeleteGist = async (id: string) => {
await ky
.delete(`${getBackendURL()}/gists/${id}`, {
- credentials: 'include',
+ credentials: "include",
})
- .then()
- return id
-}
+ .then();
+ return id;
+};
//hooks
-export const useGists = () => {
+export const useGists = ({
+ offset,
+ limit,
+}: {
+ offset?: number;
+ limit?: number;
+}) => {
const { data, error, isPending } = useQuery({
- queryKey: ['gists'],
- queryFn: fetchGists,
- })
+ queryKey: ["gists", offset?.toString(), limit?.toString()],
+ queryFn: () =>
+ fetchGists({
+ offset: offset || 0,
+ limit: limit || 50,
+ }),
+ staleTime: 5000,
+ });
- return { data, error, isPending }
-}
+ return { data: data?.gists, nb_pages: data?.nb_pages, error, isPending };
+};
export const useGist = (gistId: string) => {
const { data, error, isPending } = useQuery({
- queryKey: ['gists', gistId],
+ queryKey: ["gists", gistId],
queryFn: () => fetchGist(gistId),
- })
- return { data, error, isPending }
-}
+ });
+ return { data, error, isPending };
+};
export const useCreateGist = ({ onSuccess }: { onSuccess: () => void }) => {
- const queryClient = useQueryClient() // Access the Query Client
+ const queryClient = useQueryClient(); // Access the Query Client
const { mutate, error, data, isPending } = useMutation({
mutationFn: (gist: CreateGistPayload) => {
- return fetchCreateGist(gist)
+ return fetchCreateGist(gist);
},
onSuccess: (newGist) => {
- queryClient.setQueryData(['gists'], (oldData: any) => {
+ queryClient.setQueryData(["gists"], (oldData: any) => {
// Assuming oldData is an array, you might need to adjust this based on your actual data structure
- return [...(oldData || []), newGist]
- })
+ return [...(oldData || []), newGist];
+ });
// Call the onSuccess callback if provided
if (onSuccess) {
- onSuccess()
+ onSuccess();
}
},
- })
- return { mutate, error, data, isPending }
-}
+ });
+ return { mutate, error, data, isPending };
+};
function updateNewGistInCache(queryClient: any, newGist: Gist) {
- queryClient.setQueryData(['gists'], (oldData: any) => {
+ queryClient.setQueryData(["gists"], (oldData: any) => {
// Assuming oldData is an array, you might need to adjust this based on your actual data structure
return oldData.map((gist: Gist) => {
if (gist.id === newGist.id) {
- return newGist
+ return newGist;
}
- return gist
- })
- })
+ return gist;
+ });
+ });
}
export const usePatchGistName = ({ onSuccess }: { onSuccess: () => void }) => {
- const queryClient = useQueryClient() // Access the Query Client
+ const queryClient = useQueryClient(); // Access the Query Client
const { mutate, error, data, isPending } = useMutation({
mutationFn: (payload: PatchGistNamePayload) => {
- return fetchPatchGistName(payload)
+ return fetchPatchGistName(payload);
},
onSuccess: (newGist) => {
- updateNewGistInCache(queryClient, newGist) // Call the onSuccess callback if provided
+ updateNewGistInCache(queryClient, newGist); // Call the onSuccess callback if provided
if (onSuccess) {
- onSuccess()
+ onSuccess();
}
},
- })
- return { mutate, error, data, isPending }
-}
+ });
+ return { mutate, error, data, isPending };
+};
-export const usePatchGistContent = ({ onSuccess }: { onSuccess: () => void }) => {
- const queryClient = useQueryClient() // Access the Query Client
+export const usePatchGistContent = ({
+ onSuccess,
+}: {
+ onSuccess: () => void;
+}) => {
+ const queryClient = useQueryClient(); // Access the Query Client
const { mutate, error, data, isPending } = useMutation({
mutationFn: (payload: PatchGistContentPayload) => {
- return fetchPatchGistContent(payload)
+ return fetchPatchGistContent(payload);
},
onSuccess: (newGist) => {
- updateNewGistInCache(queryClient, newGist) // Call the onSuccess callback if provided
+ updateNewGistInCache(queryClient, newGist); // Call the onSuccess callback if provided
if (onSuccess) {
- onSuccess()
+ onSuccess();
}
},
- })
- return { mutate, error, data, isPending }
-}
+ });
+ return { mutate, error, data, isPending };
+};
-export const useDeleteGist = ({ onSuccess }: { onSuccess: (id: string) => void }) => {
- const queryClient = useQueryClient()
+export const useDeleteGist = ({
+ onSuccess,
+}: {
+ onSuccess: (id: string) => void;
+}) => {
+ const queryClient = useQueryClient();
const { mutate, error, data, isPending } = useMutation({
mutationFn: (id: string) => {
- return fetchDeleteGist(id)
+ return fetchDeleteGist(id);
},
onSuccess: (gistID) => {
- queryClient.setQueryData(['gists'], (oldData: any) => {
- return oldData.filter((gist: Gist) => gist.id !== gistID.toString())
- })
- onSuccess(gistID.toString())
+ queryClient.setQueryData(["gists"], (oldData: any) => {
+ return oldData.filter((gist: Gist) => gist.id !== gistID.toString());
+ });
+ onSuccess(gistID.toString());
},
- })
+ });
- return { mutate, error, data, isPending }
-}
+ return { mutate, error, data, isPending };
+};
diff --git a/src/lib/queries/orgs.queries.tsx b/src/lib/queries/orgs.queries.tsx
index fdce775..158c704 100644
--- a/src/lib/queries/orgs.queries.tsx
+++ b/src/lib/queries/orgs.queries.tsx
@@ -1,31 +1,32 @@
-import ky from 'ky'
-import { getBackendURL } from '../utils'
-import { Org } from '@/types'
-import { ApiGist } from './gists.queries'
-import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
-import { useState } from 'react'
+import ky from "ky";
+import { getBackendURL } from "../utils";
+import { Org } from "@/types";
+import { ApiGist } from "./gists.queries";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+import { useState } from "react";
interface AllApiOrg {
- id: string
- name: string
+ id: string;
+ name: string;
}
interface ApiOrg {
- id: string
- name: string
- gists: string[]
+ id: string;
+ name: string;
+ gists: string[];
}
const fetchOrgs = async () => {
- let orgs: Org[] = []
+ let orgs: Org[] = [];
const json = await ky
.get(`${getBackendURL()}/orgs`, {
- credentials: 'include',
+ credentials: "include",
+ retry: 0,
})
- .json()
+ .json();
if (!json) {
- return []
+ return [];
}
for (let org of json) {
@@ -33,131 +34,134 @@ const fetchOrgs = async () => {
id: org.id,
name: org.name,
gists: [],
- }
+ };
try {
const orgDetail = await ky
.get(`${getBackendURL()}/orgs/${org.id}`, {
- credentials: 'include',
- retry: 1,
+ credentials: "include",
+ retry: 0,
})
- .json()
+ .json();
for (let gistId of orgDetail.gists) {
const gist = await ky
.get(`${getBackendURL()}/gists/${gistId}`, {
- credentials: 'include',
+ credentials: "include",
})
- .json()
- data.gists.push({
+ .json();
+ data.gists.push({
id: gist.id,
name: gist.name,
code: gist.content,
- })
+ });
}
} catch (e) {
// orgs can be empty therefore we need to catch the error and ignore it
}
- orgs.push(data)
+ orgs.push(data);
}
- return orgs
-}
+ return orgs;
+};
const fetchOrg = async (orgId: string): Promise => {
const json = await ky
.get(`${getBackendURL()}/orgs/${orgId}`, {
- credentials: 'include',
+ credentials: "include",
+ retry: 0,
})
- .json()
+ .json();
return {
id: json.id,
name: json.name,
gists: json.gists.map((gistId) => {
return {
id: gistId,
- name: '',
- code: '',
- }
+ name: "",
+ code: "",
+ };
}),
- }
-}
+ };
+};
const fetchCreateOrg = async (name: string): Promise => {
const json = await ky
.post(`${getBackendURL()}/orgs`, {
- credentials: 'include',
+ credentials: "include",
json: { name },
+ retry: 0,
})
- .json()
+ .json();
return {
id: json.id,
name: json.name,
gists: [],
- }
-}
+ };
+};
const fetchDeleteOrg = async (id: string) => {
await ky
.delete(`${getBackendURL()}/orgs/${id}`, {
- credentials: 'include',
+ credentials: "include",
+ retry: 0,
})
- .json()
-}
+ .json();
+};
//hooks
export const useOrgs = () => {
const { data, error, isPending } = useQuery({
- queryKey: ['orgs'],
+ queryKey: ["orgs"],
queryFn: fetchOrgs,
- })
- return { data, error, isPending }
-}
+ });
+ return { data, error, isPending };
+};
export const useOrg = (orgId: string) => {
const { data, error, isPending } = useQuery({
- queryKey: ['orgs', orgId],
+ queryKey: ["orgs", orgId],
queryFn: () => fetchOrg(orgId),
- })
- return { data, error, isPending }
-}
+ });
+ return { data, error, isPending };
+};
export const useCreateOrg = ({ onSuccess }: { onSuccess: () => void }) => {
- const queryClient = useQueryClient()
+ const queryClient = useQueryClient();
const { mutate, error, data, isPending } = useMutation({
mutationFn: (name: string) => fetchCreateOrg(name),
onSuccess: (newOrg) => {
- queryClient.setQueryData(['orgs'], (orgs: Org[] | undefined) => {
- return orgs ? [...orgs, newOrg] : [newOrg]
- })
+ queryClient.setQueryData(["orgs"], (orgs: Org[] | undefined) => {
+ return orgs ? [...orgs, newOrg] : [newOrg];
+ });
if (onSuccess) {
- onSuccess()
+ onSuccess();
}
},
- })
+ });
- return { mutate, error, data, isPending }
-}
+ return { mutate, error, data, isPending };
+};
export const useDeleteOrgs = ({ onSuccess }: { onSuccess: () => void }) => {
- const queryClient = useQueryClient()
- const [orgID, setOrgID] = useState('')
+ const queryClient = useQueryClient();
+ const [orgID, setOrgID] = useState("");
const { mutate, error, data, isPending } = useMutation({
mutationFn: (id: string) => {
- setOrgID(id)
- return fetchDeleteOrg(id)
+ setOrgID(id);
+ return fetchDeleteOrg(id);
},
onSuccess: () => {
- queryClient.setQueryData(['orgs'], (orgs: Org[] | undefined) => {
- return orgs?.filter((org) => org.id !== orgID)
- })
+ queryClient.setQueryData(["orgs"], (orgs: Org[] | undefined) => {
+ return orgs?.filter((org) => org.id !== orgID);
+ });
if (onSuccess) {
- onSuccess()
+ onSuccess();
}
},
- })
+ });
- return { mutate, error, data, isPending }
-}
+ return { mutate, error, data, isPending };
+};