Files
k-tv/k-tv-frontend/hooks/use-channels.ts
Gabriel Kaszewski 81df6eb8ff feat: add access control to channels with various modes
- Introduced AccessMode enum to define channel access levels: Public, PasswordProtected, AccountRequired, and OwnerOnly.
- Updated Channel and ProgrammingBlock entities to include access_mode and access_password_hash fields.
- Enhanced create and update channel functionality to handle access mode and password.
- Implemented access checks in channel routes based on the defined access modes.
- Modified frontend components to support channel creation and editing with access control options.
- Added ChannelPasswordModal for handling password input when accessing restricted channels.
- Updated API calls to include channel and block passwords as needed.
- Created database migrations to add access_mode and access_password_hash columns to channels table.
2026-03-14 01:45:10 +01:00

120 lines
3.7 KiB
TypeScript

"use client";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { api } from "@/lib/api";
import { useAuthContext } from "@/context/auth-context";
import type { CreateChannelRequest, UpdateChannelRequest } from "@/lib/types";
export function useConfig() {
return useQuery({
queryKey: ["config"],
queryFn: () => api.config.get(),
staleTime: Infinity, // config doesn't change at runtime
});
}
export function useChannels() {
const { token } = useAuthContext();
return useQuery({
queryKey: ["channels"],
// Public endpoint — no token needed for TV viewing
queryFn: () => api.channels.list(token ?? ""),
});
}
export function useChannel(id: string) {
const { token } = useAuthContext();
return useQuery({
queryKey: ["channel", id],
queryFn: () => api.channels.get(id, token!),
enabled: !!token && !!id,
});
}
export function useCreateChannel() {
const { token } = useAuthContext();
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: CreateChannelRequest) =>
api.channels.create(data, token!),
onSuccess: (channel) => {
queryClient.invalidateQueries({ queryKey: ["channels"] });
toast.success(`Channel "${channel.name}" created`);
},
onError: (e: Error) => toast.error(e.message),
});
}
export function useUpdateChannel() {
const { token } = useAuthContext();
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }: { id: string; data: UpdateChannelRequest }) =>
api.channels.update(id, data, token!),
onSuccess: (updated) => {
queryClient.invalidateQueries({ queryKey: ["channels"] });
queryClient.invalidateQueries({ queryKey: ["channel", updated.id] });
toast.success(`Channel "${updated.name}" saved`);
},
onError: (e: Error) => toast.error(e.message),
});
}
export function useDeleteChannel() {
const { token } = useAuthContext();
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => api.channels.delete(id, token!),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["channels"] });
toast.success("Channel deleted");
},
onError: (e: Error) => toast.error(e.message),
});
}
export function useGenerateSchedule() {
const { token } = useAuthContext();
const queryClient = useQueryClient();
return useMutation({
mutationFn: (channelId: string) =>
api.schedule.generate(channelId, token!),
onSuccess: (_, channelId) => {
queryClient.invalidateQueries({ queryKey: ["schedule", channelId] });
toast.success("Schedule generated");
},
onError: (e: Error) => toast.error(`Schedule failed: ${e.message}`),
});
}
export function useActiveSchedule(channelId: string) {
const { token } = useAuthContext();
return useQuery({
queryKey: ["schedule", channelId],
queryFn: () => api.schedule.getActive(channelId, token!),
enabled: !!token && !!channelId,
retry: false,
});
}
export function useCurrentBroadcast(channelId: string, channelPassword?: string) {
const { token } = useAuthContext();
return useQuery({
queryKey: ["broadcast", channelId, channelPassword],
queryFn: () => api.schedule.getCurrentBroadcast(channelId, token ?? "", channelPassword),
enabled: !!channelId,
refetchInterval: 30_000,
retry: false,
});
}
export function useEpg(channelId: string, from?: string, until?: string, channelPassword?: string) {
const { token } = useAuthContext();
return useQuery({
queryKey: ["epg", channelId, from, until, channelPassword],
queryFn: () => api.schedule.getEpg(channelId, token ?? "", from, until, channelPassword),
enabled: !!channelId,
});
}