telegram-files/web/src/hooks/use-telegram-account.tsx
2024-12-21 11:47:52 +08:00

111 lines
3 KiB
TypeScript

"use client";
import { useParams, useRouter } from "next/navigation";
import { useToast } from "@/hooks/use-toast";
import { createContext, useContext, useEffect, useMemo, useState } from "react";
import type { TelegramAccount } from "@/lib/types";
import useSWR from "swr";
import useSWRMutation from "swr/mutation";
import { POST } from "@/lib/api";
interface TelegramAccountContextType {
isLoading: boolean;
getAccounts: (status?: "active" | "inactive") => TelegramAccount[];
accountId: string | undefined;
account?: TelegramAccount;
handleAccountChange: (accountId: string) => void;
resetAccount: () => void;
}
const TelegramAccountContext = createContext<
TelegramAccountContextType | undefined
>(undefined);
interface TelegramAccountProviderProps {
children: React.ReactNode;
}
export const TelegramAccountProvider: React.FC<
TelegramAccountProviderProps
> = ({ children }) => {
const {
data: accounts,
isLoading,
isValidating,
} = useSWR<TelegramAccount[]>(`/telegrams`);
const params = useParams();
const router = useRouter();
const { toast } = useToast();
const routerAccountId = params.accountId as string;
const [accountId, setAccountId] = useState<string | undefined>(
routerAccountId,
);
const { trigger: triggerChange } = useSWRMutation(
"/telegrams/change",
(key, { arg }: { arg: { accountId: string | undefined } }) => {
return POST(`${key}?telegramId=${arg.accountId}`);
},
);
useEffect(() => {
if (accountId) {
void triggerChange({ accountId });
}
}, [accountId, triggerChange]);
const account = useMemo(
() => accounts?.find((a) => a.id === accountId),
[accountId, accounts],
);
const getAccounts = (status?: "active" | "inactive") => {
if (!status) return accounts ?? [];
return accounts?.filter((a) => a.status === status) ?? [];
};
const handleAccountChange = (newAccountId: string) => {
if (newAccountId === accountId && routerAccountId) {
return;
}
const account = accounts?.find((a) => a.id === newAccountId);
if (!account) return;
setAccountId(newAccountId);
if (account.status === "active") {
toast({
title: "Account Changed",
description: `Switched to ${accounts?.find((a) => a.id === newAccountId)?.name}'s account`,
});
router.push(`/account/${newAccountId}`);
}
};
const handleAccountReset = () => {
void triggerChange({ accountId: "" }).then(() => setAccountId(undefined));
};
return (
<TelegramAccountContext.Provider
value={{
isLoading: isLoading || isValidating,
getAccounts,
accountId,
account,
handleAccountChange,
resetAccount: handleAccountReset,
}}
>
{children}
</TelegramAccountContext.Provider>
);
};
export function useTelegramAccount() {
const context = useContext(TelegramAccountContext);
if (!context) {
throw new Error(
"useTelegramAccount must be used within a TelegramAccountProvider",
);
}
return context;
}