[skip ci] Initial commit — CodexBar Mobile Expo app
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { useState, useCallback, useEffect } from "react";
|
||||
import { fetchClaudeOrgs, fetchClaudeUsage } from "@/lib/api/claudeApi";
|
||||
import {
|
||||
loadClaudeSessionKey,
|
||||
saveClaudeSessionKey,
|
||||
clearClaudeSessionKey,
|
||||
} from "@/lib/storage";
|
||||
import type { ClaudeUsageResponse } from "@/types/claude";
|
||||
|
||||
type Status = "idle" | "loading" | "success" | "error";
|
||||
|
||||
export function useClaudeUsage() {
|
||||
const [sessionKey, setSessionKey] = useState<string | null>(null);
|
||||
const [pendingKey, setPendingKey] = useState("");
|
||||
const [usage, setUsage] = useState<ClaudeUsageResponse | null>(null);
|
||||
const [status, setStatus] = useState<Status>("idle");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
loadClaudeSessionKey().then((stored) => {
|
||||
if (stored) setSessionKey(stored);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const saveKey = useCallback(async () => {
|
||||
const trimmed = pendingKey.trim();
|
||||
if (!trimmed.startsWith("sk-ant-")) {
|
||||
setError("Session key must start with sk-ant-");
|
||||
return;
|
||||
}
|
||||
await saveClaudeSessionKey(trimmed);
|
||||
setSessionKey(trimmed);
|
||||
setPendingKey("");
|
||||
setError(null);
|
||||
}, [pendingKey]);
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
if (!sessionKey) return;
|
||||
setStatus("loading");
|
||||
setError(null);
|
||||
try {
|
||||
const orgs = await fetchClaudeOrgs(sessionKey);
|
||||
if (!orgs.length) throw new Error("NO_ORGS_FOUND");
|
||||
const orgUuid = orgs[0].uuid;
|
||||
const data = await fetchClaudeUsage(sessionKey, orgUuid);
|
||||
setUsage(data);
|
||||
setStatus("success");
|
||||
} catch (e: unknown) {
|
||||
const msg = e instanceof Error ? e.message : "UNKNOWN_ERROR";
|
||||
setError(msg);
|
||||
setStatus("error");
|
||||
if (msg === "TOKEN_EXPIRED") {
|
||||
await clearClaudeSessionKey();
|
||||
setSessionKey(null);
|
||||
}
|
||||
}
|
||||
}, [sessionKey]);
|
||||
|
||||
useEffect(() => {
|
||||
if (sessionKey) void refresh();
|
||||
}, [sessionKey]);
|
||||
|
||||
const clearKey = useCallback(async () => {
|
||||
await clearClaudeSessionKey();
|
||||
setSessionKey(null);
|
||||
setUsage(null);
|
||||
setStatus("idle");
|
||||
setError(null);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
sessionKey,
|
||||
pendingKey,
|
||||
setPendingKey,
|
||||
usage,
|
||||
status,
|
||||
error,
|
||||
saveKey,
|
||||
refresh,
|
||||
clearKey,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user