Files
youtube-studio-flow/backend/src/modules/calendar/calendar.service.ts
T

71 lines
2.2 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { PrismaService } from '../../shared/prisma/prisma.service';
@Injectable()
export class CalendarService {
constructor(private readonly prisma: PrismaService) {}
async getEntries(view: string, date: string) {
const { start, end } = this.parseRange(view, date);
const videos = await this.prisma.video.findMany({
where: {
OR: [
{ scheduledAt: { gte: start, lte: end } },
{ publishedAt: { gte: start, lte: end } },
],
},
include: {
template: { select: { id: true, name: true } },
},
orderBy: { scheduledAt: 'asc' },
});
const allCollabIds = [...new Set(videos.flatMap((v) => (v.collaboratorIds as string[]) ?? []))];
const collabs = allCollabIds.length > 0
? await this.prisma.collaborator.findMany({
where: { id: { in: allCollabIds } },
select: { id: true, name: true, youtubeLink: true },
})
: [];
const collabMap = new Map(collabs.map((c) => [c.id, c]));
return videos.map((v) => ({
videoId: v.id,
title: v.title,
date: v.scheduledAt ?? v.publishedAt,
templateName: v.template?.name,
collaborators: ((v.collaboratorIds as string[]) ?? []).map((id) => collabMap.get(id)).filter(Boolean),
lintStatus: v.lintStatus,
channelId: v.channelId,
privacyStatus: v.privacyStatus,
}));
}
private parseRange(view: string, date: string): { start: Date; end: Date } {
const [year, month] = date.split('-').map(Number);
if (view === 'month') {
const start = new Date(year, month - 1, 1);
const end = new Date(year, month, 0, 23, 59, 59);
return { start, end };
}
if (view === 'week') {
const base = new Date(year, month - 1, 1);
const start = new Date(base);
start.setDate(base.getDate() - base.getDay());
const end = new Date(start);
end.setDate(start.getDate() + 6);
end.setHours(23, 59, 59);
return { start, end };
}
// agenda: next 30 days from date
const start = new Date(date);
const end = new Date(start);
end.setDate(start.getDate() + 30);
return { start, end };
}
}