diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index e4dbc01..57d4ffc --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,14 @@ -# Environment variables (DO NOT COMMIT) -.env - -# Node dependencies -node_modules/ - -# Build output (if using a bundler or React later) -dist/ -build/ - -# Logs -npm-debug.log* -yarn-debug.log* -yarn-error.log* +# Environment variables (DO NOT COMMIT) +.env + +# Node dependencies +node_modules/ + +# Build output (if using a bundler or React later) +dist/ +build/ + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/backend/.dockerignore b/backend/.dockerignore old mode 100644 new mode 100755 index 3edde31..6fa4692 --- a/backend/.dockerignore +++ b/backend/.dockerignore @@ -1,5 +1,5 @@ -node_modules -.git -dist -build -*.log +node_modules +.git +dist +build +*.log diff --git a/backend/Dockerfile b/backend/Dockerfile old mode 100644 new mode 100755 index 4cee512..79c6597 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,12 +1,12 @@ -FROM node:20-alpine - -WORKDIR /app - -COPY package*.json ./ -RUN npm install - -COPY . . - -EXPOSE 5000 - -CMD ["node", "server.js"] +FROM node:20-alpine + +WORKDIR /app + +COPY package*.json ./ +RUN npm install + +COPY . . + +EXPOSE 5000 + +CMD ["npm", "run", "dev"] \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json old mode 100644 new mode 100755 index 729a8ef..613173b --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -13,6 +13,7 @@ "devDependencies": { "cpx": "^1.5.0", "esbuild": "^0.25.5", + "nodemon": "^3.1.11", "rimraf": "^6.0.1" } }, @@ -1512,6 +1513,15 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -1632,6 +1642,12 @@ "node": ">=0.10.0" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2144,6 +2160,208 @@ "node": ">= 0.6" } }, + "node_modules/nodemon": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.11.tgz", + "integrity": "sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/nodemon/node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nodemon/node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nodemon/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/nodemon/node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nodemon/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/nodemon/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/nodemon/node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nodemon/node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nodemon/node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nodemon/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/nodemon/node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nodemon/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/nodemon/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", @@ -2455,6 +2673,18 @@ "split2": "^4.1.0" } }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -2526,6 +2756,12 @@ "node": ">= 0.10" } }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, "node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -3091,6 +3327,18 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", @@ -3271,6 +3519,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -3605,6 +3865,18 @@ "minimist": "^1.1.0" } }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -3677,6 +3949,15 @@ "node": ">=0.6" } }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, "node_modules/type-is": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", @@ -3690,6 +3971,12 @@ "node": ">= 0.6" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", diff --git a/backend/package.json b/backend/package.json old mode 100644 new mode 100755 index bf3ce45..2bcdf1a --- a/backend/package.json +++ b/backend/package.json @@ -8,10 +8,11 @@ "devDependencies": { "cpx": "^1.5.0", "esbuild": "^0.25.5", + "nodemon": "^3.1.11", "rimraf": "^6.0.1" }, "scripts": { "build": "rimraf dist && node build.js && cpx \"public/**/*\" dist/public", - "dev": "node server.js" + "dev": "nodemon server.js" } } diff --git a/backend/server.js b/backend/server.js old mode 100644 new mode 100755 index eeac8c2..b40ef9c --- a/backend/server.js +++ b/backend/server.js @@ -15,12 +15,26 @@ const pool = new Pool({ port: 5432, }); + + app.use(express.json()); + +const allowedOrigins = [ + "http://localhost:3000", + "https://mygroceryapp.com", +]; app.use(cors({ - origin: "http://localhost:3000", + origin: function (origin, callback) { + if (!origin) return callback(null, true); + if (allowedOrigins.includes(origin)) return callback(null, true); + if (/^http:\/\/192\.168\.\d+\.\d+/.test(origin)) return callback(null, true); + callback(new Error("Not allowed by CORS")); + }, methods: ["GET", "POST"], })); + + app.get('/', async (req, res) => { const { query } = req.query; const { rows } = await pool.query( diff --git a/build.js b/build.js old mode 100644 new mode 100755 index 43f361a..d6033bf --- a/build.js +++ b/build.js @@ -1,15 +1,15 @@ -// build.js -const esbuild = require('esbuild'); -const fs = require('fs'); - -// Ensure dist folder exists -if (!fs.existsSync('dist')) fs.mkdirSync('dist', { recursive: true }); - -esbuild.build({ - entryPoints: ['server.js'], - outfile: 'dist/server.js', - bundle: true, - platform: 'node', - target: 'node18', - minify: false, -}).catch(() => process.exit(1)); +// build.js +const esbuild = require('esbuild'); +const fs = require('fs'); + +// Ensure dist folder exists +if (!fs.existsSync('dist')) fs.mkdirSync('dist', { recursive: true }); + +esbuild.build({ + entryPoints: ['server.js'], + outfile: 'dist/server.js', + bundle: true, + platform: 'node', + target: 'node18', + minify: false, +}).catch(() => process.exit(1)); diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml old mode 100644 new mode 100755 index 38e40f8..9a67a38 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,21 +1,24 @@ -services: - frontend: - build: - context: ./frontend - dockerfile: Dockerfile.dev - environment: - - NODE_ENV=development - volumes: - - ./frontend:/app - - /app/node_modules - ports: - - "3000:5173" - depends_on: - - backend - - backend: - build: ./backend - ports: - - "5000:5000" - env_file: +services: + frontend: + build: + context: ./frontend + dockerfile: Dockerfile.dev + environment: + - NODE_ENV=development + volumes: + - ./frontend:/app + - /app/node_modules + ports: + - "3000:5173" + depends_on: + - backend + + backend: + build: ./backend + volumes: + - ./backend:/app + - /app/node_modules + ports: + - "5000:5000" + env_file: - ./backend/.env \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml old mode 100644 new mode 100755 index c37f1c7..775351a --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,16 +1,16 @@ -services: - frontend: - build: ./frontend - environment: - - MODE_ENV=production - ports: - - "3000:80" - depends_on: - - backend - - backend: - build: ./backend - ports: - - "5000:5000" - env_file: +services: + frontend: + build: ./frontend + environment: + - MODE_ENV=production + ports: + - "3000:80" + depends_on: + - backend + + backend: + build: ./backend + ports: + - "5000:5000" + env_file: - ./backend/.env \ No newline at end of file diff --git a/frontend/.dockerignore b/frontend/.dockerignore old mode 100644 new mode 100755 index 3edde31..6fa4692 --- a/frontend/.dockerignore +++ b/frontend/.dockerignore @@ -1,5 +1,5 @@ -node_modules -.git -dist -build -*.log +node_modules +.git +dist +build +*.log diff --git a/frontend/.gitignore b/frontend/.gitignore old mode 100644 new mode 100755 diff --git a/frontend/Dockerfile b/frontend/Dockerfile old mode 100644 new mode 100755 index 5a17e8e..24ba17d --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,15 +1,15 @@ -FROM node:20-alpine AS build - -WORKDIR /app -COPY package*.json ./ -RUN npm install - -COPY . . -RUN npm run build - -FROM nginx:alpine -COPY --from=build /app/dist /usr/share/nginx/html - -EXPOSE 80 - -CMD ["nginx", "-g", "daemon off;"] +FROM node:20-alpine AS build + +WORKDIR /app +COPY package*.json ./ +RUN npm install + +COPY . . +RUN npm run build + +FROM nginx:alpine +COPY --from=build /app/dist /usr/share/nginx/html + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/frontend/Dockerfile.dev b/frontend/Dockerfile.dev old mode 100644 new mode 100755 index 6bb1779..7c4ad25 --- a/frontend/Dockerfile.dev +++ b/frontend/Dockerfile.dev @@ -1,16 +1,16 @@ -# FROM node:20-alpine -FROM node:20-slim -# FROM node:20 - - -WORKDIR /app - -COPY package*.json ./ -RUN npm install - -COPY . . - -ENV CHOKIDAR_USEPOLLING=true - -EXPOSE 5173 -CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] +# FROM node:20-alpine +FROM node:20-slim +# FROM node:20 + + +WORKDIR /app + +COPY package*.json ./ +RUN npm install + +COPY . . + +ENV CHOKIDAR_USEPOLLING=true + +EXPOSE 5173 +CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] diff --git a/frontend/README.md b/frontend/README.md old mode 100644 new mode 100755 diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js old mode 100644 new mode 100755 diff --git a/frontend/index.html b/frontend/index.html old mode 100644 new mode 100755 index 95f6df6..6e33df9 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,12 +1,12 @@ - - - - - - Costco Grocery List - - -
- - - + + + + + + Costco Grocery List + + +
+ + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json old mode 100644 new mode 100755 diff --git a/frontend/package.json b/frontend/package.json old mode 100644 new mode 100755 diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg old mode 100644 new mode 100755 diff --git a/frontend/src/App.css b/frontend/src/App.css old mode 100644 new mode 100755 diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/assets/react.svg b/frontend/src/assets/react.svg old mode 100644 new mode 100755 diff --git a/frontend/src/components/GroceryItem.tsx b/frontend/src/components/GroceryItem.tsx old mode 100644 new mode 100755 index 7daeba2..a352287 --- a/frontend/src/components/GroceryItem.tsx +++ b/frontend/src/components/GroceryItem.tsx @@ -1,23 +1,23 @@ -import type { GroceryItemType } from "../types"; - -interface Props { - item: GroceryItemType; - onClick: (id: number) => void; -} - -export default function GroceryItem({ item, onClick }: Props) { - return ( -
  • onClick(item.id)} - style={{ - padding: "0.5em", - background: "#e9ecef", - marginBottom: "0.5em", - borderRadius: "4px", - cursor: "pointer", - }} - > - {item.item_name} ({item.quantity}) -
  • - ); -} +import type { GroceryItemType } from "../types"; + +interface Props { + item: GroceryItemType; + onClick: (id: number) => void; +} + +export default function GroceryItem({ item, onClick }: Props) { + return ( +
  • onClick(item.id)} + style={{ + padding: "0.5em", + background: "#e9ecef", + marginBottom: "0.5em", + borderRadius: "4px", + cursor: "pointer", + }} + > + {item.item_name} ({item.quantity}) +
  • + ); +} diff --git a/frontend/src/components/SuggestionList.tsx b/frontend/src/components/SuggestionList.tsx old mode 100644 new mode 100755 index fc52eaa..51fd676 --- a/frontend/src/components/SuggestionList.tsx +++ b/frontend/src/components/SuggestionList.tsx @@ -1,40 +1,40 @@ -interface Props { - suggestions: string[]; - onSelect: (value: string) => void; -} - -export default function SuggestionList({ suggestions, onSelect }: Props) { - if (!suggestions.length) return null; - - return ( - - ); -} +interface Props { + suggestions: string[]; + onSelect: (value: string) => void; +} + +export default function SuggestionList({ suggestions, onSelect }: Props) { + if (!suggestions.length) return null; + + return ( + + ); +} diff --git a/frontend/src/config.ts b/frontend/src/config.ts old mode 100644 new mode 100755 diff --git a/frontend/src/index.css b/frontend/src/index.css old mode 100644 new mode 100755 diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/types.ts b/frontend/src/types.ts old mode 100644 new mode 100755 index 0f76ab5..3448404 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -1,5 +1,5 @@ -export interface GroceryItemType { - id: number; - item_name: string; - quantity: number; -} +export interface GroceryItemType { + id: number; + item_name: string; + quantity: number; +} diff --git a/frontend/tsconfig.app.json b/frontend/tsconfig.app.json old mode 100644 new mode 100755 diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json old mode 100644 new mode 100755 diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json old mode 100644 new mode 100755 diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts old mode 100644 new mode 100755