mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-22 21:29:05 +00:00
feat: migrate components to React Query hooks
- Add comprehensive API hooks for all operations - Migrate rooms page to use React Query mutations - Update transcript title component to use mutation hook - Refactor share/privacy component with proper error handling - Remove direct API client usage in favor of hooks
This commit is contained in:
@@ -15,9 +15,15 @@ import {
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import { useEffect, useState } from "react";
|
||||
import useApi from "../../lib/useApi";
|
||||
import useRoomList from "./useRoomList";
|
||||
import { ApiError, Room } from "../../lib/api-types";
|
||||
import {
|
||||
useRoomCreate,
|
||||
useRoomUpdate,
|
||||
useRoomDelete,
|
||||
useZulipStreams,
|
||||
useZulipTopics,
|
||||
} from "../../lib/api-hooks";
|
||||
import { RoomList } from "./_components/RoomList";
|
||||
import { PaginationPage } from "../browse/_components/Pagination";
|
||||
|
||||
@@ -75,64 +81,42 @@ export default function RoomsList() {
|
||||
const [room, setRoom] = useState(roomInitialState);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [editRoomId, setEditRoomId] = useState("");
|
||||
const api = useApi();
|
||||
// TODO seems to be no setPage calls
|
||||
const [page, setPage] = useState<number>(1);
|
||||
const { loading, response, refetch } = useRoomList(PaginationPage(page));
|
||||
const [streams, setStreams] = useState<Stream[]>([]);
|
||||
const [topics, setTopics] = useState<Topic[]>([]);
|
||||
const [nameError, setNameError] = useState("");
|
||||
const [linkCopied, setLinkCopied] = useState("");
|
||||
interface Stream {
|
||||
stream_id: number;
|
||||
name: string;
|
||||
}
|
||||
const [selectedStreamId, setSelectedStreamId] = useState<number | null>(null);
|
||||
|
||||
// React Query hooks
|
||||
const createRoomMutation = useRoomCreate();
|
||||
const updateRoomMutation = useRoomUpdate();
|
||||
const deleteRoomMutation = useRoomDelete();
|
||||
const { data: streams = [] } = useZulipStreams();
|
||||
const { data: topics = [] } = useZulipTopics(selectedStreamId);
|
||||
interface Topic {
|
||||
name: string;
|
||||
}
|
||||
|
||||
// Update selected stream ID when zulip stream changes
|
||||
useEffect(() => {
|
||||
const fetchZulipStreams = async () => {
|
||||
if (!api) return;
|
||||
|
||||
try {
|
||||
const response = await api.v1ZulipGetStreams();
|
||||
setStreams(response);
|
||||
} catch (error) {
|
||||
console.error("Error fetching Zulip streams:", error);
|
||||
if (room.zulipStream && streams.length > 0) {
|
||||
const selectedStream = streams.find(
|
||||
(s: any) => s.name === room.zulipStream,
|
||||
);
|
||||
if (selectedStream) {
|
||||
setSelectedStreamId((selectedStream as any).stream_id);
|
||||
}
|
||||
};
|
||||
|
||||
if (room.zulipAutoPost) {
|
||||
fetchZulipStreams();
|
||||
} else {
|
||||
setSelectedStreamId(null);
|
||||
}
|
||||
}, [room.zulipAutoPost, !api]);
|
||||
}, [room.zulipStream, streams]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchZulipTopics = async () => {
|
||||
if (!api || !room.zulipStream) return;
|
||||
try {
|
||||
const selectedStream = streams.find((s) => s.name === room.zulipStream);
|
||||
if (selectedStream) {
|
||||
const response = await api.v1ZulipGetTopics({
|
||||
streamId: selectedStream.stream_id,
|
||||
});
|
||||
setTopics(response);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching Zulip topics:", error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchZulipTopics();
|
||||
}, [room.zulipStream, streams, api]);
|
||||
|
||||
const streamOptions: SelectOption[] = streams.map((stream) => {
|
||||
const streamOptions: SelectOption[] = streams.map((stream: any) => {
|
||||
return { label: stream.name, value: stream.name };
|
||||
});
|
||||
|
||||
const topicOptions: SelectOption[] = topics.map((topic) => ({
|
||||
const topicOptions: SelectOption[] = topics.map((topic: any) => ({
|
||||
label: topic.name,
|
||||
value: topic.name,
|
||||
}));
|
||||
@@ -175,13 +159,15 @@ export default function RoomsList() {
|
||||
};
|
||||
|
||||
if (isEditing) {
|
||||
await api?.v1RoomsUpdate({
|
||||
roomId: editRoomId,
|
||||
requestBody: roomData,
|
||||
await updateRoomMutation.mutateAsync({
|
||||
params: {
|
||||
path: { room_id: editRoomId },
|
||||
},
|
||||
body: roomData,
|
||||
});
|
||||
} else {
|
||||
await api?.v1RoomsCreate({
|
||||
requestBody: roomData,
|
||||
await createRoomMutation.mutateAsync({
|
||||
body: roomData,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -226,8 +212,10 @@ export default function RoomsList() {
|
||||
|
||||
const handleDeleteRoom = async (roomId: string) => {
|
||||
try {
|
||||
await api?.v1RoomsDelete({
|
||||
roomId,
|
||||
await deleteRoomMutation.mutateAsync({
|
||||
params: {
|
||||
path: { room_id: roomId },
|
||||
},
|
||||
});
|
||||
refetch();
|
||||
} catch (err) {
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
createListCollection,
|
||||
} from "@chakra-ui/react";
|
||||
import { LuShare2 } from "react-icons/lu";
|
||||
import useApi from "../../lib/useApi";
|
||||
import { useTranscriptUpdate } from "../../lib/api-hooks";
|
||||
import useSessionUser from "../../lib/useSessionUser";
|
||||
import { CustomSession } from "../../lib/types";
|
||||
import ShareLink from "./shareLink";
|
||||
@@ -54,12 +54,9 @@ export default function ShareAndPrivacy(props: ShareAndPrivacyProps) {
|
||||
);
|
||||
const [shareLoading, setShareLoading] = useState(false);
|
||||
const requireLogin = featureEnabled("requireLogin");
|
||||
const api = useApi();
|
||||
const updateTranscriptMutation = useTranscriptUpdate();
|
||||
|
||||
const updateShareMode = async (selectedValue: string) => {
|
||||
if (!api)
|
||||
throw new Error("ShareLink's API should always be ready at this point");
|
||||
|
||||
const selectedOption = shareOptionsData.find(
|
||||
(option) => option.value === selectedValue,
|
||||
);
|
||||
@@ -71,16 +68,23 @@ export default function ShareAndPrivacy(props: ShareAndPrivacyProps) {
|
||||
share_mode: selectedValue as "public" | "semi-private" | "private",
|
||||
};
|
||||
|
||||
const updatedTranscript = await api.v1TranscriptUpdate({
|
||||
transcriptId: props.transcriptResponse.id,
|
||||
requestBody,
|
||||
});
|
||||
setShareMode(
|
||||
shareOptionsData.find(
|
||||
(option) => option.value === updatedTranscript.share_mode,
|
||||
) || shareOptionsData[0],
|
||||
);
|
||||
setShareLoading(false);
|
||||
try {
|
||||
const updatedTranscript = await updateTranscriptMutation.mutateAsync({
|
||||
params: {
|
||||
path: { transcript_id: props.transcriptResponse.id },
|
||||
},
|
||||
body: requestBody,
|
||||
});
|
||||
setShareMode(
|
||||
shareOptionsData.find(
|
||||
(option) => option.value === (updatedTranscript as any).share_mode,
|
||||
) || shareOptionsData[0],
|
||||
);
|
||||
} catch (err) {
|
||||
console.error("Failed to update share mode:", err);
|
||||
} finally {
|
||||
setShareLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const userId = useSessionUser().id;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import { UpdateTranscript } from "../../lib/api-types";
|
||||
import useApi from "../../lib/useApi";
|
||||
import { useTranscriptUpdate } from "../../lib/api-hooks";
|
||||
import { Heading, IconButton, Input, Flex, Spacer } from "@chakra-ui/react";
|
||||
import { LuPen } from "react-icons/lu";
|
||||
|
||||
@@ -14,24 +14,27 @@ const TranscriptTitle = (props: TranscriptTitle) => {
|
||||
const [displayedTitle, setDisplayedTitle] = useState(props.title);
|
||||
const [preEditTitle, setPreEditTitle] = useState(props.title);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const api = useApi();
|
||||
const updateTranscriptMutation = useTranscriptUpdate();
|
||||
|
||||
const updateTitle = async (newTitle: string, transcriptId: string) => {
|
||||
if (!api) return;
|
||||
try {
|
||||
const requestBody: UpdateTranscript = {
|
||||
title: newTitle,
|
||||
};
|
||||
const updatedTranscript = await api?.v1TranscriptUpdate({
|
||||
transcriptId,
|
||||
requestBody,
|
||||
await updateTranscriptMutation.mutateAsync({
|
||||
params: {
|
||||
path: { transcript_id: transcriptId },
|
||||
},
|
||||
body: requestBody,
|
||||
});
|
||||
if (props.onUpdate) {
|
||||
props.onUpdate(newTitle);
|
||||
}
|
||||
console.log("Updated transcript:", updatedTranscript);
|
||||
console.log("Updated transcript title:", newTitle);
|
||||
} catch (err) {
|
||||
console.error("Failed to update transcript:", err);
|
||||
// Revert title on error
|
||||
setDisplayedTitle(preEditTitle);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user