first commit
This commit is contained in:
236
app/usr/2_mychannel/page.tsx
Normal file
236
app/usr/2_mychannel/page.tsx
Normal file
@@ -0,0 +1,236 @@
|
||||
"use client";
|
||||
import CalenderSelector from "@/app/components/CalenderSelector";
|
||||
import Modal from "@/app/components/Modal";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
|
||||
export default function Page() {
|
||||
const [isreqmodal, setIsreqmodal] = useState(false);
|
||||
const [chanellist, setChanellist] = useState<string[]>([]);
|
||||
const [contentlist, setContentlist] = useState<{
|
||||
id: string;
|
||||
email: string;
|
||||
pubDate: string;
|
||||
is_approved: boolean;
|
||||
is_certified: boolean;
|
||||
video_count: number;
|
||||
views: number;
|
||||
revenue: number;
|
||||
pendingRevenue: number;
|
||||
}[]>([]);
|
||||
|
||||
const [channelList, setChannelList] = useState<{
|
||||
id: string;
|
||||
handle: string;
|
||||
createtime: string;
|
||||
is_approved: boolean;
|
||||
icon: string;
|
||||
}[]>([]);
|
||||
|
||||
|
||||
const [registerCode, setRegisterCode] = useState<string>("");
|
||||
|
||||
const handleInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
|
||||
const formatNumberWithCommas = (number: number): string => {
|
||||
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
};
|
||||
|
||||
const get_code = async () => {
|
||||
if (handleInputRef.current && handleInputRef.current.value) {
|
||||
const inputValue = handleInputRef.current.value;
|
||||
if (confirm(`핸들 "${inputValue}" 의 등록 코드를 발급하시겠습니까?`)) {
|
||||
try {
|
||||
const response = await fetch(`/api/channel_code?handle=${inputValue}`);
|
||||
if (response.status === 409) {
|
||||
alert("이미 등록된 요청입니다. 기존 코드를 사용합니다.");
|
||||
const data = await response.json();
|
||||
setRegisterCode(data.randomcode);
|
||||
return;
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new Error('서버 응답이 올바르지 않습니다.');
|
||||
}
|
||||
const data = await response.json();
|
||||
setRegisterCode(data.randomcode);
|
||||
} catch (error) {
|
||||
console.error('채널 코드 요청 중 오류 발생:', error);
|
||||
alert('채널 코드를 가져오는데 실패했습니다. 다시 시도해주세요.');
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else{ alert("채널 핸들을 입력해주세요"); }
|
||||
}
|
||||
|
||||
const register_channel = async () => {
|
||||
if (handleInputRef.current && handleInputRef.current.value) {
|
||||
const inputValue = handleInputRef.current.value;
|
||||
try {
|
||||
const response = await fetch(`/api/register_channel?handle=${encodeURIComponent(inputValue)}`);
|
||||
const data = await response.json();
|
||||
if (!response.ok) {
|
||||
alert(data?.error ?? '등록 요청 실패');
|
||||
return;
|
||||
}
|
||||
alert('등록 요청을 전송했습니다.');
|
||||
setIsreqmodal(false);
|
||||
} catch (error) {
|
||||
console.error('등록 요청 중 오류:', error);
|
||||
alert('등록 요청 실패');
|
||||
}
|
||||
} else { alert("채널 핸들을 입력해주세요"); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const fetchListChannel = async () => {
|
||||
try {
|
||||
const resp = await fetch('/api/list_channel', { cache: 'no-store' });
|
||||
const data = await resp.json();
|
||||
setChannelList(data.items);
|
||||
console.log('list_channel:', data);
|
||||
} catch (e) {
|
||||
console.error('list_channel 요청 에러:', e);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// 세션 이메일 기준 채널 목록 조회 로그
|
||||
fetchListChannel();
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<div className="flex flex-col w-[100vw] p-2 lg:w-[calc(100vw-350px)] max-w-[1200px] mx-auto">
|
||||
<div className="flex flex-row h-[64px] justify-between items-center">
|
||||
<div className="flex flex-row h-[36px]">
|
||||
|
||||
</div>
|
||||
<div className="flex flex-row h-[36px]">
|
||||
<div
|
||||
className="w-[104px] h-[36px] rounded-lg flex items-center justify-center bg-[#F94B37] border-[#D73B29] text-white cursor-pointer hover:bg-[#D73B29]"
|
||||
onClick={() => {setIsreqmodal(true); setRegisterCode("")}}
|
||||
>
|
||||
채널 등록
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="
|
||||
border-1 border-[#e6e9ef] rounded-lg bg-white overflow-y-auto
|
||||
">
|
||||
<table className="w-full h-full border-separate border-spacing-y-1 table-fixed px-[10px]">
|
||||
<colgroup>
|
||||
<col className="min-w-[250px] max-w-[300px]"/>
|
||||
<col className="w-[120px]"/>
|
||||
<col className="w-[80px]"/>
|
||||
<col className="w-[100px]"/>
|
||||
<col className="w-[100px]"/>
|
||||
<col className="w-[110px]"/>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr className="sticky top-0 bg-white h-[49px] ">
|
||||
<th className="border-b-1 right-border border-[#e6e9ef] ">채널 핸들</th>
|
||||
<th className="border-b-1 right-border border-[#e6e9ef] ">등록 날짜</th>
|
||||
<th className="border-b-1 right-border border-[#e6e9ef] ">승인여부</th>
|
||||
<th className="border-b-1 right-border border-[#e6e9ef] ">영상수</th>
|
||||
<th className="border-b-1 right-border border-[#e6e9ef] ">조회수</th>
|
||||
<th className="border-b-1 border-[#e6e9ef] ">예상수익</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
channelList.map((channel)=>{
|
||||
return (
|
||||
<tr key={channel.id} className="h-[54px] border-1 border-[#e6e9ef] rounded-lg font-semibold">
|
||||
<td className="right-border rounded-l-lg border-l-1 border-t-1 border-b-1 border-[#e6e9ef] pl-2 h-[54px] " >
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<div className="w-[48px] h-[48px] rounded-full border-1 border-[#e6e9ef]">
|
||||
<img src={channel.icon} alt="channel icon" className="w-[48px] h-[48px] rounded-full" />
|
||||
</div>
|
||||
<div>
|
||||
{channel.handle}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="right-border border-b-1 border-t-1 border-[#e6e9ef] text-center whitespace-nowrap overflow-hidden">{channel.createtime.split("T")[0]}</td>
|
||||
<td className="right-border border-b-1 border-t-1 border-[#e6e9ef] text-center whitespace-nowrap overflow-hidden">{channel.is_approved? "승인" : "미승인"}</td>
|
||||
<td className="right-border border-b-1 border-t-1 border-[#e6e9ef] text-center"> - </td>
|
||||
<td className="right-border border-b-1 border-t-1 border-[#e6e9ef] text-center"> - </td>
|
||||
<td className="border-b-1 border-t-1 border-[#e6e9ef] border-r-1 rounded-r-lg text-center"> - </td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<Modal isOpen={isreqmodal} onClose={() => setIsreqmodal(false)}>
|
||||
<div className=" w-full h-full flex flex-col justify-start gap-5">
|
||||
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="text-3xl font-semibold">채널등록</div>
|
||||
<div className="text-3xl cursor-pointer" onClick={() => setIsreqmodal(false)}>
|
||||
<svg width="18" height="17" viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M0.951569 0.451569C1.4202 -0.0170597 2.18 -0.0170597 2.64863 0.451569L9.0001 6.80304L15.3516 0.451569C15.8202 -0.0170597 16.58 -0.0170597 17.0486 0.451569C17.5173 0.920199 17.5173 1.68 17.0486 2.14863L10.6972 8.5001L17.0486 14.8516C17.5173 15.3202 17.5173 16.08 17.0486 16.5486C16.58 17.0173 15.8202 17.0173 15.3516 16.5486L9.0001 10.1972L2.64863 16.5486C2.18 17.0173 1.4202 17.0173 0.951569 16.5486C0.48294 16.08 0.48294 15.3202 0.951569 14.8516L7.30304 8.5001L0.951569 2.14863C0.48294 1.68 0.48294 0.920199 0.951569 0.451569Z" fill="#848484" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex flex-col sh-[287px]">
|
||||
<div className="flex flex-col justify-between">
|
||||
<div className="text-lg font-semibold text-black">핸들</div>
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="w-[400px] h-[56px] border-[#d5d5d5] border-1 bg-white text-black font-normal rounded-lg flex items-center justify-center text-md p-1 px-2">
|
||||
<input type="text" className="w-full h-full border-none outline-none" ref={handleInputRef}/>
|
||||
</div>
|
||||
<div className="ml-2 w-[140px] h-[50px] border-[#D73B29] bg-[#F94B37] text-white font-bold rounded-lg flex items-center justify-center text-xl cursor-pointer hover:bg-[#D73B29] transition-colors" onClick={() => get_code()}>
|
||||
코드 발급
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex flex-col justify-between mt-5">
|
||||
<div className="text-lg font-semibold text-black">채널 등록 코드</div>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
|
||||
|
||||
<div className="w-full h-[56px] border-[#d5d5d5] border-1 bg-white text-black font-normal rounded-lg flex items-center justify-start text-xl p-5">
|
||||
{registerCode ? registerCode : "코드를 발급해주세요"}
|
||||
</div>
|
||||
{registerCode && (
|
||||
<div
|
||||
className="w-[45px] h-[56px] border-[#d5d5d5] border-1 bg-white rounded-lg flex items-center justify-center cursor-pointer"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(registerCode);
|
||||
}}
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20 9H11C9.89543 9 9 9.89543 9 11V20C9 21.1046 9.89543 22 11 22H20C21.1046 22 22 21.1046 22 20V11C22 9.89543 21.1046 9 20 9Z" stroke="#666666" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
<path d="M5 15H4C3.46957 15 2.96086 14.7893 2.58579 14.4142C2.21071 14.0391 2 13.5304 2 13V4C2 3.46957 2.21071 2.96086 2.58579 2.58579C2.96086 2.21071 3.46957 2 4 2H13C13.5304 2 14.0391 2.21071 14.4142 2.58579C14.7893 2.96086 15 3.46957 15 4V5" stroke="#666666" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div className="mt-3 w-[100%-50px] h-[56px] border-[#D73B29] bg-[#F94B37] text-white font-bold rounded-lg flex items-center justify-center text-xl cursor-pointer hover:bg-[#D73B29] transition-colors" onClick={() => register_channel()}>
|
||||
채널 등록
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user