| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- 'use client';
- import { useCallback, useState } from 'react';
- import { fetchApi } from '@/lib/utils/client';
- import type { LiveChannelItem, LiveChannelListResponse } from '@/types/response/channel/live-list';
- import LiveChannelCard from './LiveChannelCard';
- import LiveChannelEmpty from './LiveChannelEmpty';
- type Props = {
- initialChannels: LiveChannelItem[];
- initialTotal: number;
- pageSize: number;
- };
- export default function LiveChannelGrid({ initialChannels, initialTotal, pageSize }: Props)
- {
- const [channels, setChannels] = useState<LiveChannelItem[]>(initialChannels);
- const [total, setTotal] = useState(initialTotal);
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState<string|null>(null);
- const hasMore = channels.length < total;
- const handleLoadMore = useCallback(async () => {
- if (loading || !hasMore) {
- return;
- }
- setLoading(true);
- setError(null);
- try {
- const res = await fetchApi<LiveChannelListResponse>(`/api/channel/live-list?limit=${pageSize}&offset=${channels.length}`, { silent: true });
- if (res.success && res.data) {
- setChannels(prev => [...prev, ...res.data!.channels]);
- setTotal(res.data.total);
- } else {
- setError('목록을 불러오지 못했습니다.');
- }
- } catch {
- setError('목록을 불러오지 못했습니다.');
- } finally {
- setLoading(false);
- }
- }, [channels.length, hasMore, loading, pageSize]);
- if (channels.length === 0) {
- return <LiveChannelEmpty />;
- }
- return (
- <section className="home__live" aria-labelledby="home-live-heading">
- <header className="home__section-head">
- <h2 id="home-live-heading" className="home__section-title">
- 라이브 방송 중
- <span className="home__section-count" aria-label={`총 ${total}개 채널`}>
- {total.toLocaleString()}
- </span>
- </h2>
- </header>
- <div className="live-grid" role="list">
- {channels.map((ch, idx) => (
- <div key={ch.channelSID} role="listitem" className="live-grid__item">
- <LiveChannelCard channel={ch} priority={idx < 4} />
- </div>
- ))}
- </div>
- {hasMore && (
- <div className="home__load-more">
- <button
- type="button"
- onClick={handleLoadMore}
- disabled={loading}
- className="home__load-more-btn"
- aria-label={loading ? '불러오는 중' : '더 보기'}
- >
- {loading ? '불러오는 중...' : '더 보기'}
- </button>
- </div>
- )}
- {error && (
- <div role="alert" className="home__error">{error}</div>
- )}
- </section>
- );
- }
|