From cff0d5e60cd7f25c4c101dda94a2b180ac52b94a Mon Sep 17 00:00:00 2001 From: harsharajkumar-273 Date: Wed, 15 Jul 2026 14:59:46 +0530 Subject: [PATCH 1/2] feat: Add Dockerization for seamless local development (#510) --- README.md | 17 +++++++++++++ client/.dockerignore | 6 +++++ client/Dockerfile | 19 +++++++++++++++ docker-compose.yml | 57 ++++++++++++++++++++++++++++++++++++++++++++ server/.dockerignore | 5 ++++ server/Dockerfile | 19 +++++++++++++++ 6 files changed, 123 insertions(+) create mode 100644 client/.dockerignore create mode 100644 client/Dockerfile create mode 100644 docker-compose.yml create mode 100644 server/.dockerignore create mode 100644 server/Dockerfile diff --git a/README.md b/README.md index 8286467..1de2d21 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,23 @@ StudyMatePlus/ - npm 9 or newer - MongoDB connection string +## Docker Setup (Alternative & Recommended) + +If you have Docker and Docker Compose installed, you can spin up the complete development environment (Frontend, Backend, and a local MongoDB instance) with a single command. This avoids having to configure local environments manually. + +### 1. Build and start containers + +```bash +docker-compose up --build +``` + +### 2. Access the application + +- **Frontend client**: http://localhost:3000 +- **Backend API**: http://localhost:5000 + +The services support volume mounting, so any changes you make in `client/` or `server/` will automatically sync and trigger hot reloading inside the containers. + ## Local setup ### 1. Clone the repository diff --git a/client/.dockerignore b/client/.dockerignore new file mode 100644 index 0000000..d59faa1 --- /dev/null +++ b/client/.dockerignore @@ -0,0 +1,6 @@ +node_modules +build +npm-debug.log +.env +.git +.gitignore diff --git a/client/Dockerfile b/client/Dockerfile new file mode 100644 index 0000000..a7f06be --- /dev/null +++ b/client/Dockerfile @@ -0,0 +1,19 @@ +FROM node:20-alpine + +# Set working directory +WORKDIR /app + +# Copy package files first +COPY package*.json ./ + +# Install dependencies +RUN npm install + +# Copy the rest of the application files +COPY . . + +# Expose react port +EXPOSE 3000 + +# Start client server +CMD ["npm", "start"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..42c948f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,57 @@ +services: + mongodb: + image: mongo:latest + container_name: studymateplus-db + ports: + - "27017:27017" + volumes: + - mongo-data:/data/db + networks: + - studymateplus-network + + server: + build: + context: ./server + dockerfile: Dockerfile + container_name: studymateplus-server + ports: + - "5000:5000" + environment: + - PORT=5000 + - MONGO_URI=mongodb://mongodb:27017/studymateplus + - JWT_SECRET=studymateplus_secret_key_123 + - CLIENT_URL=http://localhost:3000 + volumes: + - ./server:/app + - /app/node_modules + depends_on: + - mongodb + networks: + - studymateplus-network + + client: + build: + context: ./client + dockerfile: Dockerfile + container_name: studymateplus-client + ports: + - "3000:3000" + environment: + - REACT_APP_API_URL=http://localhost:5000 + - WDS_SOCKET_PORT=0 + stdin_open: true + tty: true + volumes: + - ./client:/app + - /app/node_modules + depends_on: + - server + networks: + - studymateplus-network + +volumes: + mongo-data: + +networks: + studymateplus-network: + driver: bridge diff --git a/server/.dockerignore b/server/.dockerignore new file mode 100644 index 0000000..c6cdbfa --- /dev/null +++ b/server/.dockerignore @@ -0,0 +1,5 @@ +node_modules +npm-debug.log +.env +.git +.gitignore diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..516ef57 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,19 @@ +FROM node:20-alpine + +# Set working directory +WORKDIR /app + +# Copy package files first +COPY package*.json ./ + +# Install dependencies +RUN npm install + +# Copy the rest of the application files +COPY . . + +# Expose server port +EXPOSE 5000 + +# Start server in dev mode +CMD ["npm", "run", "dev"] From 010b706b13d956ade7bb10163a3d8b0cee79ec5e Mon Sep 17 00:00:00 2001 From: harsharajkumar-273 Date: Wed, 15 Jul 2026 15:03:12 +0530 Subject: [PATCH 2/2] fix: prevent adding empty or whitespace-only tasks to To-Do list (#670) --- client/src/pages/Todo.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/client/src/pages/Todo.js b/client/src/pages/Todo.js index 0057af0..d2232b9 100644 --- a/client/src/pages/Todo.js +++ b/client/src/pages/Todo.js @@ -24,6 +24,7 @@ export default function Todo() { const [form, setForm] = useState(defaultForm); const [isEditing, setIsEditing] = useState(false); const [showModal, setShowModal] = useState(false); + const [error, setError] = useState(""); useEffect(() => { // Load tasks and normalize recurring tasks so their deadlines are not in the past @@ -77,11 +78,20 @@ export default function Todo() { setForm(defaultForm); setIsEditing(false); setShowModal(false); + setError(""); } function handleSubmit(e) { e.preventDefault(); - if (!form.title || !form.deadline) return alert("Please provide a title and deadline"); + if (!form.title || !form.title.trim()) { + setError("Task title is required"); + return; + } + if (!form.deadline) { + setError("Deadline is required"); + return; + } + setError(""); if (isEditing) { setTasks((prev) => prev.map((t) => (t.id === form.id ? { ...t, ...form } : t))); @@ -172,10 +182,14 @@ export default function Todo() {
+ {error &&
{error}
}
setForm((f) => ({ ...f, title: e.target.value }))} + onChange={(e) => { + setForm((f) => ({ ...f, title: e.target.value })); + if (error) setError(""); + }} placeholder="Task title" />