pretty it up
This commit is contained in:
@@ -5,7 +5,7 @@ export const runtime = "nodejs";
|
||||
import { getServerSession } from "next-auth/next";
|
||||
import { authOptions } from "@/lib/auth";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { uploadToDrive, updateDriveFile, generateReportMarkdown, getGoogleAuth } from "@/lib/google-drive";
|
||||
import { uploadToDrive, updateDriveFile, generateReportHTML, getGoogleAuth } from "@/lib/google-drive";
|
||||
|
||||
export async function POST(
|
||||
req: Request,
|
||||
@@ -35,7 +35,7 @@ export async function POST(
|
||||
return NextResponse.json({ error: "Report not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
const markdown = generateReportMarkdown(report);
|
||||
const htmlContent = generateReportHTML(report);
|
||||
const fileName = `WFH_Report_${new Date(report.date).toISOString().split('T')[0]}_${report.user.name}`;
|
||||
|
||||
// Fetch designated folder ID from settings
|
||||
@@ -48,10 +48,10 @@ export async function POST(
|
||||
|
||||
if (report.driveFileId) {
|
||||
// Update the existing Drive file in place
|
||||
driveFile = await updateDriveFile(auth, report.driveFileId, markdown);
|
||||
driveFile = await updateDriveFile(auth, report.driveFileId, htmlContent);
|
||||
} else {
|
||||
// First export — create a new Drive file and store its ID
|
||||
driveFile = await uploadToDrive(auth, fileName, markdown, folderSetting?.value);
|
||||
driveFile = await uploadToDrive(auth, fileName, htmlContent, folderSetting?.value);
|
||||
await prisma.report.update({
|
||||
where: { id },
|
||||
data: { driveFileId: driveFile.id },
|
||||
|
||||
@@ -63,7 +63,7 @@ export async function uploadToDrive(auth: any, fileName: string, content: string
|
||||
}
|
||||
|
||||
const media = {
|
||||
mimeType: 'text/markdown',
|
||||
mimeType: 'text/html',
|
||||
body: Readable.from([content]),
|
||||
};
|
||||
|
||||
@@ -84,7 +84,7 @@ export async function updateDriveFile(auth: any, fileId: string, content: string
|
||||
const drive = google.drive({ version: 'v3', auth });
|
||||
|
||||
const media = {
|
||||
mimeType: 'text/markdown',
|
||||
mimeType: 'text/html',
|
||||
body: Readable.from([content]),
|
||||
};
|
||||
|
||||
@@ -101,23 +101,66 @@ export async function updateDriveFile(auth: any, fileId: string, content: string
|
||||
}
|
||||
}
|
||||
|
||||
export function generateReportMarkdown(report: any) {
|
||||
let md = `# WFH Daily Report - ${new Date(report.date).toLocaleDateString()}\n`;
|
||||
md += `**Employee:** ${report.user.name}\n`;
|
||||
md += `**Manager:** ${report.managerName}\n\n`;
|
||||
export function generateReportHTML(report: any) {
|
||||
const dateObj = new Date(report.date);
|
||||
const dateStr = dateObj.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
|
||||
const plannedTasks = report.tasks.filter((t: any) => t.type === 'PLANNED');
|
||||
const completedTasks = report.tasks.filter((t: any) => t.type === 'COMPLETED');
|
||||
|
||||
md += `## Planned Tasks\n`;
|
||||
report.tasks.filter((t: any) => t.type === 'PLANNED').forEach((t: any) => {
|
||||
md += `- [ ] ${t.description} (Est: ${t.timeEstimate})\n`;
|
||||
if (t.notes) md += ` - Notes: ${t.notes}\n`;
|
||||
});
|
||||
const cellStyle = "padding: 10px; border-bottom: 1px solid #e2e8f0; font-family: Arial, sans-serif; font-size: 11pt;";
|
||||
const headerStyle = "padding: 12px 10px; background-color: #f1f5f9; border-bottom: 2px solid #cbd5e1; font-family: Arial, sans-serif; font-size: 11pt; font-weight: bold; text-align: left; color: #334155;";
|
||||
|
||||
md += `\n## Completed Tasks\n`;
|
||||
report.tasks.filter((t: any) => t.type === 'COMPLETED').forEach((t: any) => {
|
||||
md += `- [x] ${t.description}\n`;
|
||||
md += ` - Status: ${t.status}\n`;
|
||||
if (t.link) md += ` - Work Link: ${t.link}\n`;
|
||||
});
|
||||
return `
|
||||
<html>
|
||||
<body style="font-family: Arial, sans-serif; color: #334155; line-height: 1.6; max-width: 800px; margin: 0 auto; padding: 20px;">
|
||||
<h1 style="color: #0f172a; border-bottom: 3px solid #3b82f6; padding-bottom: 10px; font-family: Arial, sans-serif; margin-bottom: 20px;">WFH Daily Report</h1>
|
||||
|
||||
<div style="background-color: #f8fafc; padding: 20px; border-left: 4px solid #3b82f6; border-radius: 4px; margin-bottom: 30px; font-family: Arial, sans-serif;">
|
||||
<p style="margin: 0 0 8px 0; font-size: 11pt;"><strong>Date:</strong> ${dateStr}</p>
|
||||
<p style="margin: 0 0 8px 0; font-size: 11pt;"><strong>Employee:</strong> ${report.user.name}</p>
|
||||
<p style="margin: 0; font-size: 11pt;"><strong>Manager:</strong> ${report.managerName || 'N/A'}</p>
|
||||
</div>
|
||||
|
||||
return md;
|
||||
<h2 style="color: #1e293b; margin-top: 30px; margin-bottom: 15px; font-family: Arial, sans-serif;">Planned Tasks</h2>
|
||||
${plannedTasks.length > 0 ? `
|
||||
<table style="width: 100%; border-collapse: collapse; margin-bottom: 30px;">
|
||||
<tr>
|
||||
<th style="${headerStyle} width: 45%;">Description</th>
|
||||
<th style="${headerStyle} width: 20%;">Estimate</th>
|
||||
<th style="${headerStyle} width: 35%;">Notes</th>
|
||||
</tr>
|
||||
${plannedTasks.map((t: any) => `
|
||||
<tr>
|
||||
<td style="${cellStyle}">${t.description}</td>
|
||||
<td style="${cellStyle} color: #64748b;">${t.timeEstimate || '-'}</td>
|
||||
<td style="${cellStyle} color: #64748b;">${t.notes || '-'}</td>
|
||||
</tr>
|
||||
`).join('')}
|
||||
</table>
|
||||
` : `<p style="font-style: italic; color: #94a3b8; font-family: Arial, sans-serif; margin-bottom: 30px;">No planned tasks for today.</p>`}
|
||||
|
||||
<h2 style="color: #1e293b; margin-top: 30px; margin-bottom: 15px; font-family: Arial, sans-serif;">Completed Tasks</h2>
|
||||
${completedTasks.length > 0 ? `
|
||||
<table style="width: 100%; border-collapse: collapse; margin-bottom: 30px;">
|
||||
<tr>
|
||||
<th style="${headerStyle} width: 40%;">Description</th>
|
||||
<th style="${headerStyle} width: 20%;">Status</th>
|
||||
<th style="${headerStyle} width: 40%;">Work Link</th>
|
||||
</tr>
|
||||
${completedTasks.map((t: any) => `
|
||||
<tr>
|
||||
<td style="${cellStyle}">${t.description}</td>
|
||||
<td style="${cellStyle} font-weight: bold; color: #059669;">${t.status || 'Done'}</td>
|
||||
<td style="${cellStyle}">${t.link ? `<a href="${t.link}" style="color: #2563eb; text-decoration: none;">${t.link}</a>` : '-'}</td>
|
||||
</tr>
|
||||
`).join('')}
|
||||
</table>
|
||||
` : `<p style="font-style: italic; color: #94a3b8; font-family: Arial, sans-serif; margin-bottom: 30px;">No completed tasks reported today.</p>`}
|
||||
|
||||
<div style="margin-top: 50px; font-size: 9pt; color: #cbd5e1; text-align: center; border-top: 1px solid #e2e8f0; padding-top: 20px; font-family: Arial, sans-serif;">
|
||||
Generated automatically by WFH App
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user