"use client";
import { ActionIcon, Anchor, Avatar, Badge, Card, Group, Image, ScrollArea, Stack, Text, Tooltip } from "@mantine/core";
import { IconThumbDown, IconThumbUp } from "@tabler/icons-react";
import type { RouterInputs, RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { useRequiredBoard } from "@homarr/boards/context";
import type { MediaRequestStatus } from "@homarr/integrations/types";
import { mediaAvailabilityConfiguration, mediaRequestStatusConfiguration } from "@homarr/integrations/types";
import { useScopedI18n } from "@homarr/translation/client";
import { WidgetEmptyState } from "../../common/empty-state";
import type { WidgetComponentProps } from "../../definition";
import { NoIntegrationDataError } from "../../errors/no-data-integration";
export default function MediaServerWidget({
integrationIds,
isEditMode,
options,
width,
}: WidgetComponentProps<"mediaRequests-requestList">) {
const { data: mediaRequests } = clientApi.widget.mediaRequests.getLatestRequests.useQuery(
{
integrationIds,
},
{
refetchOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
);
const utils = clientApi.useUtils();
clientApi.widget.mediaRequests.subscribeToLatestRequests.useSubscription(
{
integrationIds,
},
{
onData(data) {
utils.widget.mediaRequests.getLatestRequests.setData({ integrationIds }, (prevData) => {
if (!prevData) return [];
const filteredData = prevData.filter(({ integrationId }) => integrationId !== data.integrationId);
const newData = filteredData.concat(
data.requests.map((request) => ({ ...request, integrationId: data.integrationId })),
);
return newData.toSorted((dataA, dataB) => {
if (dataA.status === dataB.status) {
return dataB.createdAt.getTime() - dataA.createdAt.getTime();
}
return (
mediaRequestStatusConfiguration[dataA.status].position -
mediaRequestStatusConfiguration[dataB.status].position
);
});
});
},
},
);
if (!mediaRequests) return ;
if (mediaRequests.length === 0) throw new NoIntegrationDataError();
return (
{mediaRequests.map((mediaRequest) => (
))}
);
}
interface MediaRequestCardProps {
request: RouterOutputs["widget"]["mediaRequests"]["getLatestRequests"][number];
isTiny: boolean;
options: WidgetComponentProps<"mediaRequests-requestList">["options"];
}
const MediaRequestCard = ({ request, isTiny, options }: MediaRequestCardProps) => {
const board = useRequiredBoard();
const t = useScopedI18n("widget.mediaRequests-requestList");
return (
{!isTiny && (
)}
{request.airDate?.getFullYear() ?? t("toBeDetermined")}
{!isTiny && (
{t(`availability.${request.availability}`)}
)}
{(request.requestedBy?.displayName ?? "") || "unknown"}
{request.name || "unknown"}
{request.status === "pending" ? (
) : (
)}
);
};
interface DecisionButtonsProps {
requestId: number;
integrationId: string;
}
const DecisionButtons = ({ requestId, integrationId }: DecisionButtonsProps) => {
const { mutate: mutateRequestAnswer } = clientApi.widget.mediaRequests.answerRequest.useMutation();
const t = useScopedI18n("widget.mediaRequests-requestList");
const handleDecision = (answer: RouterInputs["widget"]["mediaRequests"]["answerRequest"]["answer"]) => {
mutateRequestAnswer({
integrationId,
requestId,
answer,
});
};
return (
{
handleDecision("approve");
}}
>
{
handleDecision("decline");
}}
>
);
};
interface StatusBadgeProps {
status: MediaRequestStatus;
}
const StatusBadge = ({ status }: StatusBadgeProps) => {
const tStatus = useScopedI18n("widget.mediaRequests-requestList.status");
return (
{tStatus(status)}
);
};