From 933c0741ab66661b8c695718051f13d691a7a331 Mon Sep 17 00:00:00 2001 From: ANUJ7MADKE Date: Sat, 2 Aug 2025 15:45:32 +0530 Subject: [PATCH] docker set up --- .env | 4 + backend/Dockerfile | 17 ++++ backend/package.json | 3 +- .../migrations/20250801182528_/migration.sql | 82 +++++++++++++++++++ backend/prisma/migrations/migration_lock.toml | 3 + docker-compose.yml | 35 ++++++++ frontend/Dockerfile | 23 ++++++ frontend/nginx.conf | 11 +++ frontend/package-lock.json | 6 +- .../Report/components/FilterDataForm.jsx | 16 ++-- .../src/pages/Report/components/charts.jsx | 2 +- frontend/vite.config.js | 2 +- 12 files changed, 191 insertions(+), 13 deletions(-) create mode 100644 .env create mode 100644 backend/Dockerfile create mode 100644 backend/prisma/migrations/20250801182528_/migration.sql create mode 100644 backend/prisma/migrations/migration_lock.toml create mode 100644 docker-compose.yml create mode 100644 frontend/Dockerfile create mode 100644 frontend/nginx.conf diff --git a/.env b/.env new file mode 100644 index 0000000..6843fe0 --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +# PostgreSQL Credentials +POSTGRES_USER=postgres +POSTGRES_PASSWORD=emperorABM18 +POSTGRES_DB=Travel-Policy \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..f52b939 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,17 @@ +FROM node:22-alpine + +WORKDIR /app + +RUN apk add --no-cache openssl + +COPY package*.json ./ + +RUN npm ci --only=production + +COPY . . + +RUN npx prisma generate + +EXPOSE 3000 + +CMD ["sh", "-c", "npm run db:deploy && npm run start"] diff --git a/backend/package.json b/backend/package.json index 1dc90a8..1dc9df7 100644 --- a/backend/package.json +++ b/backend/package.json @@ -21,7 +21,8 @@ "test2": "nodemon --inspect src/server.js", "test": "echo \"Error: no test specified\" && exit 1", "dev": "nodemon src/server.js", - "start": "node src/server.js" + "start": "node src/server.js", + "db:deploy": "npx prisma migrate deploy && npx prisma generate" }, "type": "module", "keywords": [], diff --git a/backend/prisma/migrations/20250801182528_/migration.sql b/backend/prisma/migrations/20250801182528_/migration.sql new file mode 100644 index 0000000..5a34c7e --- /dev/null +++ b/backend/prisma/migrations/20250801182528_/migration.sql @@ -0,0 +1,82 @@ +-- CreateEnum +CREATE TYPE "Institute" AS ENUM ('KJSIDS', 'SKSC', 'KJSCE', 'SIRC', 'KJSIM', 'SSA', 'KJSCEd', 'DLIS', 'MSSMPA'); + +-- CreateEnum +CREATE TYPE "ApplicationStatus" AS ENUM ('REJECTED', 'ACCEPTED', 'PENDING'); + +-- CreateEnum +CREATE TYPE "Designation" AS ENUM ('HOD', 'HOI', 'VC', 'ACCOUNTS', 'FACULTY', 'STUDENT'); + +-- CreateTable +CREATE TABLE "User" ( + "profileId" TEXT NOT NULL, + "userName" TEXT NOT NULL, + "email" TEXT NOT NULL, + "password" TEXT NOT NULL, + "institute" "Institute", + "department" TEXT, + "designation" "Designation" NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("profileId") +); + +-- CreateTable +CREATE TABLE "Application" ( + "applicationId" TEXT NOT NULL, + "applicantId" TEXT NOT NULL, + "institute" "Institute" NOT NULL, + "department" TEXT NOT NULL, + "applicantName" TEXT NOT NULL, + "applicationType" TEXT NOT NULL, + "formData" JSONB NOT NULL, + "formName" TEXT NOT NULL, + "resubmission" BOOLEAN NOT NULL DEFAULT false, + "facultyValidation" "ApplicationStatus", + "hodValidation" "ApplicationStatus", + "hoiValidation" "ApplicationStatus", + "vcValidation" "ApplicationStatus", + "accountsValidation" "ApplicationStatus", + "rejectionFeedback" TEXT, + "totalExpense" DOUBLE PRECISION NOT NULL DEFAULT 0, + "proofOfTravel" BYTEA, + "proofOfAccommodation" BYTEA, + "proofOfAttendance" BYTEA, + "expenseProof0" BYTEA, + "expenseProof1" BYTEA, + "expenseProof2" BYTEA, + "expenseProof3" BYTEA, + "expenseProof4" BYTEA, + "expenseProof5" BYTEA, + "expenseProof6" BYTEA, + "expenseProof7" BYTEA, + "expenseProof8" BYTEA, + "expenseProof9" BYTEA, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Application_pkey" PRIMARY KEY ("applicationId") +); + +-- CreateTable +CREATE TABLE "_ToValidateApplications" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE INDEX "User_email_idx" ON "User"("email"); + +-- CreateIndex +CREATE INDEX "Application_applicantId_idx" ON "Application"("applicantId"); + +-- CreateIndex +CREATE INDEX "Application_createdAt_idx" ON "Application"("createdAt"); + +-- CreateIndex +CREATE UNIQUE INDEX "_ToValidateApplications_AB_unique" ON "_ToValidateApplications"("A", "B"); + +-- CreateIndex +CREATE INDEX "_ToValidateApplications_B_index" ON "_ToValidateApplications"("B"); diff --git a/backend/prisma/migrations/migration_lock.toml b/backend/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..fbffa92 --- /dev/null +++ b/backend/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b4798de --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,35 @@ +services: + # Express Backend Service + server: + build: + context: ./backend + dockerfile: Dockerfile + ports: + - "3000:3000" + environment: + - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} + depends_on: + - db + + # React Frontend Service + client: + build: + context: ./frontend + dockerfile: Dockerfile + ports: + - "5173:80" + depends_on: + - server + + # PostgreSQL Database Service + db: + image: postgres:17-alpine + environment: + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - POSTGRES_DB=${POSTGRES_DB} + volumes: + - pgdata:/var/lib/postgresql/data + +volumes: + pgdata: \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..3e89279 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,23 @@ +FROM node:22-alpine AS build + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install + +COPY . . + +RUN npm run build + +# ------------------------ + +FROM nginx:stable-alpine + +COPY --from=build /app/dist /usr/share/nginx/html + +COPY nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 0000000..cbb6356 --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,11 @@ +server { + listen 80; + server_name localhost; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 08ba80a..b893788 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -2212,9 +2212,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001695", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz", - "integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==", + "version": "1.0.30001731", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz", + "integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==", "funding": [ { "type": "opencollective", diff --git a/frontend/src/pages/Report/components/FilterDataForm.jsx b/frontend/src/pages/Report/components/FilterDataForm.jsx index 4a3903d..f768c5b 100644 --- a/frontend/src/pages/Report/components/FilterDataForm.jsx +++ b/frontend/src/pages/Report/components/FilterDataForm.jsx @@ -6,6 +6,8 @@ import * as yup from "yup"; import Input from "../../ApplicationForm/Input"; import axios from "axios"; +const BASE_URL = import.meta.env.VITE_API_BASE_URL; + function FilterDataForm({ setReportData, setLoading }) { const { role, user } = useRouteLoaderData("Validator-Root")?.data; @@ -83,13 +85,13 @@ function FilterDataForm({ setReportData, setLoading }) { if (applicationType) queryParams.append("applicationType", applicationType); const res = await axios.get( - `http://localhost:3000/validator/getReportData?${queryParams.toString()}`, - { - headers: { - "Content-Type": "application/json", - }, - withCredentials: true, - } + `${BASE_URL}/validator/getReportData?${queryParams.toString()}`, + { + headers: { + "Content-Type": "application/json", + }, + withCredentials: true, + } ); setReportData({data: res.data, query: values}); } catch (error) { diff --git a/frontend/src/pages/Report/components/charts.jsx b/frontend/src/pages/Report/components/charts.jsx index 518dd88..048afc5 100644 --- a/frontend/src/pages/Report/components/charts.jsx +++ b/frontend/src/pages/Report/components/charts.jsx @@ -19,7 +19,7 @@ import ChartDataLabels from 'chartjs-plugin-datalabels'; import Table from "./Table"; import { PDFDownloadLink, PDFViewer } from "@react-pdf/renderer"; import ApprovalVsRejectionTrends from "./map"; -import ReportPDF from "./reportPDF"; +import ReportPDF from "./ReportPDF"; // Register chart components for all three types (Line, Bar, Pie) ChartJS.register( diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 0dc4615..44356ad 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -13,6 +13,6 @@ export default defineConfig({ '/submit': process.env.VITE_APP_API_URL, }, host: true, - port: 5173, + port: process.env.VITE_APP_PORT, }, })