diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a574622 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +node_modules +.next +.git +.env +prisma/dev.db +prisma/dev.db-journal +README.md +Dockerfile +.dockerignore diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..95d9eec --- /dev/null +++ b/Dockerfile @@ -0,0 +1,45 @@ +# Build Stage +FROM node:20-alpine AS builder +WORKDIR /app + +# Install dependencies +COPY package*.json ./ +COPY prisma ./prisma/ +RUN npm install + +# Build the application +COPY . . +RUN npx prisma generate +RUN npm run build + +# Production Stage +FROM node:20-alpine AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV PORT=3000 + +# Install production dependencies only +COPY package*.json ./ +COPY prisma ./prisma/ +RUN npm install --omit=dev + +# Copy build artifacts and necessary files +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/public ./public +COPY --from=builder /app/next.config.mjs ./ +COPY --from=builder /app/next.config.ts ./ +# Optional: if you have next-pwa and custom worker files +# COPY --from=builder /app/public/sw.js ./public/ + +# Copy prisma for migrations at runtime +COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma +COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma + +# Script to run migrations and start the app +RUN echo '#!/bin/sh\nnpx prisma migrate deploy\nnpm start' > start.sh +RUN chmod +x start.sh + +EXPOSE 3000 + +CMD ["./start.sh"] diff --git a/app/actions/booking.ts b/app/actions/booking.ts index 8df88f6..c30ad39 100644 --- a/app/actions/booking.ts +++ b/app/actions/booking.ts @@ -2,6 +2,7 @@ import prisma from "@/lib/prisma" import { revalidatePath } from "next/cache" +import { headers } from "next/headers" import { sendNotification } from "@/lib/notifications" export async function createBooking(planId: string, date: Date, name: string, type: "SITTER" | "OWNER_HOME" = "SITTER") { @@ -31,10 +32,14 @@ export async function createBooking(planId: string, date: Date, name: string, ty }) if (plan?.webhookUrl && plan.notifyAll) { + const host = (await headers()).get("host") + const protocol = host?.includes("localhost") ? "http" : "https" + const planUrl = `${protocol}://${host}/dashboard/${planId}` + const dateStr = date.toLocaleDateString() const message = type === "OWNER_HOME" - ? `🏠 OWNER HOME: Marked for ${dateStr}.` - : `✅ NEW BOOKING: ${name} is sitting on ${dateStr}.` + ? `🏠 OWNER HOME: Marked for ${dateStr}.\nPlan: ${planUrl}` + : `✅ NEW BOOKING: ${name} is sitting on ${dateStr}.\nPlan: ${planUrl}` await sendNotification(plan.webhookUrl, message) } @@ -54,8 +59,12 @@ export async function deleteBooking(bookingId: number, planId: string) { }) if (booking.plan.webhookUrl) { + const host = (await headers()).get("host") + const protocol = host?.includes("localhost") ? "http" : "https" + const planUrl = `${protocol}://${host}/dashboard/${planId}` + const dateStr = booking.date.toLocaleDateString() - await sendNotification(booking.plan.webhookUrl, `🚨 CANCELLATION: ${booking.sitterName} removed their booking for ${dateStr}.`) + await sendNotification(booking.plan.webhookUrl, `🚨 CANCELLATION: ${booking.sitterName} removed their booking for ${dateStr}.\nPlan: ${planUrl}`) } revalidatePath(`/dashboard/${planId}`) diff --git a/app/actions/plan.ts b/app/actions/plan.ts index c7ca828..6a77eea 100644 --- a/app/actions/plan.ts +++ b/app/actions/plan.ts @@ -2,6 +2,7 @@ import prisma from "@/lib/prisma" import { revalidatePath } from "next/cache" +import { headers } from "next/headers" import { sendNotification } from "@/lib/notifications" export async function updatePlan(planId: string, data: { instructions?: string; webhookUrl?: string; notifyAll?: boolean }) { @@ -15,7 +16,10 @@ export async function updatePlan(planId: string, data: { instructions?: string; }) if (data.instructions && plan.webhookUrl && plan.notifyAll) { - await sendNotification(plan.webhookUrl, `📝 UPDATED: Cat instructions have been modified.`) + const host = (await headers()).get("host") + const protocol = host?.includes("localhost") ? "http" : "https" + const planUrl = `${protocol}://${host}/dashboard/${planId}` + await sendNotification(plan.webhookUrl, `📝 UPDATED: Cat instructions have been modified.\nPlan: ${planUrl}`) } revalidatePath(`/dashboard/${planId}`) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..102c979 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +services: + app: + build: . + ports: + - "3000:3000" + volumes: + - ./data:/app/prisma + restart: always