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/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() {