This commit is contained in:
2025-09-08 18:30:34 +00:00
parent c116a85ead
commit a93493fb62
15 changed files with 134 additions and 182 deletions

View File

@@ -1,115 +0,0 @@
import { NextResponse } from 'next/server';
import { auth } from '@/auth';
import { PrismaClient } from '@/app/generated/prisma';
const prisma = new PrismaClient();
function parseDateOr(value: string | null, fallback: Date): Date {
if (!value) return fallback;
const d = new Date(value);
return isNaN(d.getTime()) ? fallback : d;
}
export async function GET(request: Request) {
try {
const session = await auth();
if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
const email = session.user?.email as string | undefined;
if (!email) return NextResponse.json({ error: '세션 이메일을 찾을 수 없습니다' }, { status: 400 });
const { searchParams } = new URL(request.url);
const endDefault = new Date();
const startDefault = new Date(endDefault.getTime() - 30 * 24 * 60 * 60 * 1000);
const startParam = searchParams.get('start');
const endParam = searchParams.get('end');
const startDate = startParam ? new Date(startParam) : startDefault;
const endDate = endParam ? new Date(endParam) : endDefault;
// 날짜 경계 보정: 하루 전체 포함 (UTC 기준)
const startInclusive = new Date(startDate);
startInclusive.setUTCHours(0, 0, 0, 0);
const endInclusive = new Date(endDate);
endInclusive.setUTCHours(23, 59, 59, 999);
// 안전가드
if (endInclusive < startInclusive) endInclusive.setTime(startInclusive.getTime());
console.log('startDate', startDate.toISOString());
console.log('endDate', endDate.toISOString());
// 1) 내 핸들
const handles = await prisma.userHandle.findMany({
where: { email },
select: { id: true, handle: true, icon: true }
});
if (handles.length === 0) return NextResponse.json({ items: [] });
const handleStrs = handles.map(h => h.handle);
const handleByStr = new Map(handles.map(h => [h.handle, h] as const));
// 2) 매핑된 콘텐츠
const links = await prisma.contentHandle.findMany({
where: { handle: { in: handleStrs } },
select: { contentId: true, handle: true }
});
if (links.length === 0) return NextResponse.json({ items: [] });
const contentIds = links.map(l => l.contentId);
const normalizeId = (s: string) => (s ?? '').trim();
const contentIdsNormalized = Array.from(new Set(contentIds.map(normalizeId)));
const idsForQuery = Array.from(new Set([...contentIds, ...contentIdsNormalized]));
const handleByContentId = new Map(links.map(l => [l.contentId, l.handle] as const));
// 3) 콘텐츠 본문
const contents = await prisma.content.findMany({
where: { id: { in: contentIds } },
select: {
id: true, subject: true, pubDate: true,
views: true, premiumViews: true, watchTime: true
}
});
// 4) 기간 합계 유효조회수 (findMany로 가져와 JS에서 합산 - groupBy 일부 환경 이슈 회피)
const viewRows = await prisma.viewPerDay.findMany({
where: {
contented: { in: idsForQuery },
date: { gte: startInclusive, lte: endInclusive }
},
select: { contented: true, validViewDay: true }
});
const validSumById = new Map<string, number>();
for (const r of viewRows) {
const key = normalizeId(r.contented);
validSumById.set(key, (validSumById.get(key) ?? 0) + (r.validViewDay ?? 0));
}
// 5) 비용 단가
const cpvRow = await prisma.costPerView.findUnique({ where: { id: 1 } });
const cpv = cpvRow?.costPerView ?? 0;
const items = contents.map(c => {
const handle = handleByContentId.get(c.id) ?? '';
const handleObj = handleByStr.get(handle);
const validViews = validSumById.get(normalizeId(c.id)) ?? 0;
const expectedRevenue = validViews * cpv;
return {
id: c.id,
subject: c.subject,
pubDate: c.pubDate,
views: c.views,
premiumViews: c.premiumViews,
watchTime: c.watchTime,
handle,
handleId: handleObj?.id ?? null,
icon: handleObj?.icon ?? '',
validViews,
expectedRevenue,
};
});
return NextResponse.json({ items, cpv, start: startInclusive.toISOString(), end: endInclusive.toISOString() });
} catch (e) {
console.error('my_contents 오류:', e);
return NextResponse.json({ error: '조회 실패' }, { status: 500 });
} finally {
await prisma.$disconnect();
}
}

View File

@@ -37,9 +37,10 @@ const NavBar: React.FC<NavBarProps> = ({ isOpen, setIsOpen, user }) => {
<div className="flex-0 hidden lg:block">
<Link href="/">
<div className="flex items-center justify-center gap-1 mb-5 p-2 cursor-pointer">
<svg width="32" height="20" viewBox="0 0 32 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<Image src="/falogo2.png" alt="logo" width={64} height={64} />
{/* <svg width="32" height="20" viewBox="0 0 32 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 13.7815C0 11.1485 1.5051 9.48685 3.07055 8.61376C4.53165 7.7989 6.17151 7.56314 7.25262 7.56307H29.6288C30.9383 7.56309 32 8.65413 32 10C31.9999 11.3458 30.9383 12.4369 29.6288 12.4369H7.25262C6.70651 12.437 5.90554 12.5782 5.33295 12.8974C5.06963 13.0443 4.93117 13.1859 4.86171 13.2901C4.80809 13.3706 4.74246 13.5037 4.74246 13.7815C4.7425 14.0589 4.80813 14.1913 4.86171 14.2718C4.93111 14.376 5.06944 14.5175 5.33295 14.6644C5.90555 14.9838 6.70643 15.126 7.25262 15.1261H23.5259C24.8355 15.1261 25.8971 16.2172 25.8971 17.5631C25.8969 18.9088 24.8354 20 23.5259 20H7.25262C6.17151 19.9999 4.53165 19.763 3.07055 18.9481C1.50525 18.075 9.38884e-05 16.4143 0 13.7815ZM29.6288 0C30.9383 2.26081e-05 32 1.09107 32 2.43693C32 3.7828 30.9383 4.87385 29.6288 4.87387H14.5759C13.2664 4.87375 12.2046 3.78275 12.2046 2.43693C12.2046 1.09112 13.2664 0.000115545 14.5759 0H29.6288Z" fill="#F94B37" />
</svg>
</svg> */}
<span className="text-black text-2xl font-bold">EVERFACTORY</span>
</div>
</Link>

View File

@@ -3,6 +3,7 @@
import { signIn } from "next-auth/react"
export default function SignIn() {
return <button onClick={() => signIn("google")}>
return
<button onClick={() => signIn("google")}>
</button>
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,13 +0,0 @@
"use client";
import SignIn from "@/app/components/SignInClient";
export default function Test() {
return (
<div>
<SignIn/>
</div>
);
}

View File

@@ -44,7 +44,7 @@ export default function Home() {
<Image src="/ever_logo.png" alt="logo" width={100} height={100} />
</div>
<div className="text-white text-4xl font-bold text-center mb-3"> <br/> </div>
<div className="text-white text-md text-center mb-3">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi lobortis maximus</div>
{/* <div className="text-white text-md text-center mb-3">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi lobortis maximus</div> */}
</div>
<div>
<div className="text-white text-md text-center mb-3 cursor-pointer ">Ready to travel with us?<br/> Enter your email to create or restart your membership.</div>

View File

@@ -5,7 +5,8 @@ import DashboardClient from "@/app/components/Dashboard"; // 기존 코드 대
export default async function Page() {
const session = await auth();
if (!session) redirect("/login");
if (!session) redirect("/");
// 초기 데이터 서버에서 미리 가져오면 더 빠르고 안전 (예시)
// const [channels, contents] = await Promise.all([