Fix updating of user roles
Fix adding of items
This commit is contained in:
parent
d9c4a2caf9
commit
f30474cb5d
@ -6,6 +6,12 @@ exports.getList = async (req, res) => {
|
|||||||
res.json(items);
|
res.json(items);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.getItemByName = async (req, res) => {
|
||||||
|
const { itemName } = req.query;
|
||||||
|
const item = await List.getItemByName(itemName);
|
||||||
|
res.json(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
exports.addItem = async (req, res) => {
|
exports.addItem = async (req, res) => {
|
||||||
const { itemName, quantity } = req.body;
|
const { itemName, quantity } = req.body;
|
||||||
|
|||||||
@ -14,10 +14,10 @@ exports.getAllUsers = async (req, res) => {
|
|||||||
|
|
||||||
exports.updateUserRole = async (req, res) => {
|
exports.updateUserRole = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { id } = req.params;
|
const { id, role } = req.body;
|
||||||
const { role } = req.body;
|
|
||||||
|
|
||||||
if (!Object.values(ROLES).includes(role))
|
console.log(`Updating user ${id} to role ${role}`);
|
||||||
|
if (!Object.values(User.ROLES).includes(role))
|
||||||
return res.status(400).json({ error: "Invalid role" });
|
return res.status(400).json({ error: "Invalid role" });
|
||||||
|
|
||||||
const updated = await User.updateUserRole(id, role);
|
const updated = await User.updateUserRole(id, role);
|
||||||
|
|||||||
@ -8,23 +8,37 @@ exports.getUnboughtItems = async () => {
|
|||||||
return result.rows;
|
return result.rows;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.getItemByName = async (itemName) => {
|
||||||
exports.addOrUpdateItem = async (item_name, quantity) => {
|
|
||||||
const result = await pool.query(
|
const result = await pool.query(
|
||||||
"SELECT id, bought FROM grocery_list WHERE item_name = $1",
|
"SELECT * FROM grocery_list WHERE item_name ILIKE $1",
|
||||||
[item_name]
|
[itemName]
|
||||||
|
);
|
||||||
|
|
||||||
|
return result.rows[0] || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
exports.addOrUpdateItem = async (itemName, quantity) => {
|
||||||
|
const result = await pool.query(
|
||||||
|
"SELECT id, bought FROM grocery_list WHERE item_name ILIKE $1",
|
||||||
|
[itemName]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result.rowCount > 0) {
|
if (result.rowCount > 0) {
|
||||||
await pool.query(
|
await pool.query(
|
||||||
"UPDATE grocery_list SET quantity = $1, bought = FALSE WHERE id = $2",
|
`UPDATE grocery_list
|
||||||
|
SET quantity = $1,
|
||||||
|
bought = FALSE
|
||||||
|
WHERE id = $2`,
|
||||||
[quantity, result.rows[0].id]
|
[quantity, result.rows[0].id]
|
||||||
);
|
);
|
||||||
return result.rows[0].id;
|
return result.rows[0].id;
|
||||||
} else {
|
} else {
|
||||||
const insert = await pool.query(
|
const insert = await pool.query(
|
||||||
"INSERT INTO grocery_list (item_name, quantity) VALUES ($1, $2) RETURNING id",
|
`INSERT INTO grocery_list
|
||||||
[item_name, quantity]
|
(item_name, quantity)
|
||||||
|
VALUES ($1, $2) RETURNING id`,
|
||||||
|
[itemName, quantity]
|
||||||
);
|
);
|
||||||
return insert.rows[0].id;
|
return insert.rows[0].id;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,9 @@ const User = require("../models/user.model");
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
router.get("/", auth, requireRole(ROLES.VIEWER, ROLES.EDITOR, ROLES.ADMIN), controller.getList);
|
router.get("/", auth, requireRole(...Object.values(ROLES)), controller.getList);
|
||||||
router.get("/suggest", auth, requireRole(ROLES.VIEWER, ROLES.EDITOR, ROLES.ADMIN), controller.getSuggestions);
|
router.get("/item-by-name", auth, requireRole(...Object.values(ROLES)), controller.getItemByName);
|
||||||
|
router.get("/suggest", auth, requireRole(...Object.values(ROLES)), controller.getSuggestions);
|
||||||
|
|
||||||
|
|
||||||
router.post("/add", auth, requireRole(ROLES.EDITOR, ROLES.ADMIN), controller.addItem);
|
router.post("/add", auth, requireRole(ROLES.EDITOR, ROLES.ADMIN), controller.addItem);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import api from "./axios";
|
import api from "./axios";
|
||||||
|
|
||||||
export const getList = () => api.get("/list");
|
export const getList = () => api.get("/list");
|
||||||
export const addItem = (itemName, quantiy) => api.post("/list/add", { itemName, quantiy });
|
export const getItemByName = (itemName) => api.get("/list/item-by-name", { params: { itemName: itemName } });
|
||||||
|
export const addItem = (itemName, quantity) => api.post("/list/add", { itemName, quantity });
|
||||||
export const markBought = (id) => api.post("/list/mark-bought", { id });
|
export const markBought = (id) => api.post("/list/mark-bought", { id });
|
||||||
export const getSuggestions = (query) => api.get("/list/suggest", { params: { query: query } });
|
export const getSuggestions = (query) => api.get("/list/suggest", { params: { query: query } });
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import api from "./axios";
|
import api from "./axios";
|
||||||
|
|
||||||
export const getAllUsers = () => api.get("/admin/users");
|
export const getAllUsers = () => api.get("/admin/users");
|
||||||
export const updateRole = (id, role) => api.put(`/admin/users/${id}/role`, { role });
|
export const updateRole = (id, role) => api.put(`/admin/users`, { id, role });
|
||||||
export const deleteUser = (id) => api.delete(`/admin/users/${id}`);
|
export const deleteUser = (id) => api.delete(`/admin/users/${id}`);
|
||||||
export const checkIfUserExists = (username) => api.get(`/users/exists`, { params: { username: username } });
|
export const checkIfUserExists = (username) => api.get(`/users/exists`, { params: { username: username } });
|
||||||
@ -17,7 +17,8 @@ export default function AdminPanel() {
|
|||||||
|
|
||||||
const changeRole = async (id, role) => {
|
const changeRole = async (id, role) => {
|
||||||
const updated = await updateRole(id, role);
|
const updated = await updateRole(id, role);
|
||||||
setUsers(users.map(u => (u.id === id ? updated.data : u)))
|
if (updated.status !== 200) return;
|
||||||
|
loadUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import { addItem, getList, getSuggestions, markBought } from "../api/list";
|
import { addItem, getItemByName, getList, getSuggestions, markBought } from "../api/list";
|
||||||
import { ROLES } from "../constants/roles";
|
import { ROLES } from "../constants/roles";
|
||||||
import { AuthContext } from "../context/AuthContext";
|
import { AuthContext } from "../context/AuthContext";
|
||||||
import "../styles/GroceryList.css";
|
import "../styles/GroceryList.css";
|
||||||
@ -12,6 +12,7 @@ export default function GroceryList() {
|
|||||||
|
|
||||||
const [sortMode, setSortMode] = useState("az");
|
const [sortMode, setSortMode] = useState("az");
|
||||||
|
|
||||||
|
const [showSuggestions, setShowSuggestions] = useState(false);
|
||||||
const [itemName, setItemName] = useState("");
|
const [itemName, setItemName] = useState("");
|
||||||
const [quantity, setQuantity] = useState(1);
|
const [quantity, setQuantity] = useState(1);
|
||||||
const [suggestions, setSuggestions] = useState([]);
|
const [suggestions, setSuggestions] = useState([]);
|
||||||
@ -57,10 +58,8 @@ export default function GroceryList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log("Getting suggestions for:", text);
|
|
||||||
let suggestions = await getSuggestions(text);
|
let suggestions = await getSuggestions(text);
|
||||||
suggestions = suggestions.data.map(s => s.item_name);
|
suggestions = suggestions.data.map(s => s.item_name);
|
||||||
console.log(`Suggestions: ${suggestions}`);
|
|
||||||
setSuggestions(suggestions);
|
setSuggestions(suggestions);
|
||||||
} catch {
|
} catch {
|
||||||
setSuggestions([]);
|
setSuggestions([]);
|
||||||
@ -70,8 +69,20 @@ export default function GroceryList() {
|
|||||||
const handleAdd = async (e) => {
|
const handleAdd = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!itemName.trim()) return;
|
if (!itemName.trim()) return;
|
||||||
|
let newQuantity = quantity;
|
||||||
|
|
||||||
await addItem(itemName, quantity);
|
const item = await getItemByName(itemName);
|
||||||
|
if (item) {
|
||||||
|
let currentQuantity = item.data.quantity;
|
||||||
|
const yes = window.confirm(
|
||||||
|
`Item "${itemName}" already exists in the list. Do you want to update its quantity from ${currentQuantity} to ${currentQuantity + newQuantity}?`
|
||||||
|
);
|
||||||
|
if (!yes) return;
|
||||||
|
|
||||||
|
newQuantity += currentQuantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
await addItem(itemName, newQuantity);
|
||||||
|
|
||||||
setItemName("");
|
setItemName("");
|
||||||
setQuantity(1);
|
setQuantity(1);
|
||||||
@ -93,7 +104,6 @@ export default function GroceryList() {
|
|||||||
return (
|
return (
|
||||||
<div className="glist-body">
|
<div className="glist-body">
|
||||||
<div className="glist-container">
|
<div className="glist-container">
|
||||||
|
|
||||||
<h1 className="glist-title">Costco Grocery List</h1>
|
<h1 className="glist-title">Costco Grocery List</h1>
|
||||||
|
|
||||||
{/* Sorting dropdown */}
|
{/* Sorting dropdown */}
|
||||||
@ -117,9 +127,11 @@ export default function GroceryList() {
|
|||||||
placeholder="Item name"
|
placeholder="Item name"
|
||||||
value={itemName}
|
value={itemName}
|
||||||
onChange={(e) => handleSuggest(e.target.value)}
|
onChange={(e) => handleSuggest(e.target.value)}
|
||||||
|
onBlur={() => setTimeout(() => setShowSuggestions(false), 150)}
|
||||||
|
onClick={() => setShowSuggestions(true)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{suggestions.length > 0 && (
|
{showSuggestions && suggestions.length > 0 && (
|
||||||
<ul className="glist-suggest-box">
|
<ul className="glist-suggest-box">
|
||||||
{suggestions.map((s, i) => (
|
{suggestions.map((s, i) => (
|
||||||
<li
|
<li
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user