Fix suggestion feature
This commit is contained in:
parent
4501c47849
commit
963240ceb1
@ -44,8 +44,4 @@ app.use("/admin", adminRoutes);
|
||||
const usersRoutes = require("./routes/users.routes");
|
||||
app.use("/users", usersRoutes);
|
||||
|
||||
const suggestController = require("./routes/suggest.routes");
|
||||
app.get("/suggest", suggestController);
|
||||
|
||||
|
||||
module.exports = app;
|
||||
@ -15,14 +15,20 @@ exports.register = async (req, res) => {
|
||||
};
|
||||
|
||||
exports.login = async (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
console.log(`Login attempt for user: ${username} with password: ${password}`);
|
||||
let { username, password } = req.body;
|
||||
|
||||
username = username.toLowerCase();
|
||||
const user = await User.findByUsername(username);
|
||||
if (!user) return res.status(401).json({ message: "Invalid credentials" });
|
||||
if (!user) {
|
||||
console.log(`⚠️ Login attempt -> No user found: ${username}`);
|
||||
return res.status(401).json({ message: "User not found" });
|
||||
}
|
||||
|
||||
const valid = await bcrypt.compare(password, user.password);
|
||||
if (!valid) return res.status(401).json({ message: "Invalid credentials" });
|
||||
if (!valid) {
|
||||
console.log(`⛔ Login attempt for user ${username} with password ${password}`);
|
||||
return res.status(401).json({ message: "Invalid credentials" });
|
||||
}
|
||||
|
||||
const token = jwt.sign(
|
||||
{ id: user.id, role: user.role },
|
||||
|
||||
@ -22,3 +22,10 @@ exports.markBought = async (req, res) => {
|
||||
await List.setBought(req.body.id);
|
||||
res.json({ message: "Item marked bought" });
|
||||
};
|
||||
|
||||
|
||||
exports.getSuggestions = async (req, res) => {
|
||||
const { query } = req.query || "";
|
||||
const suggestions = await List.getSuggestions(query);
|
||||
res.json(suggestions);
|
||||
};
|
||||
@ -1,9 +0,0 @@
|
||||
const List = require("../models/list.model");
|
||||
|
||||
|
||||
exports.getHistory = async (req, res) => {
|
||||
console.log("GET /suggest called");
|
||||
const { query } = req.query;
|
||||
const items = await List.getHistory(query);
|
||||
res.json("asdf");
|
||||
};
|
||||
@ -44,7 +44,8 @@ exports.addHistoryRecord = async (itemId, quantity) => {
|
||||
);
|
||||
};
|
||||
|
||||
exports.getHistory = async (query) => {
|
||||
|
||||
exports.getSuggestions = async (query) => {
|
||||
const result = await pool.query(
|
||||
`SELECT DISTINCT item_name
|
||||
FROM grocery_list
|
||||
@ -52,9 +53,7 @@ exports.getHistory = async (query) => {
|
||||
LIMIT 10`,
|
||||
[`%${query}%`]
|
||||
);
|
||||
console.log("QUERY:");
|
||||
console.log(result.query);
|
||||
res = result.rows;
|
||||
return result.rows;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ const User = require("../models/user.model");
|
||||
|
||||
|
||||
router.get("/", auth, requireRole(ROLES.VIEWER, ROLES.EDITOR, ROLES.ADMIN), controller.getList);
|
||||
router.get("/suggest", auth, requireRole(ROLES.VIEWER, ROLES.EDITOR, ROLES.ADMIN), controller.getSuggestions);
|
||||
|
||||
|
||||
router.post("/add", auth, requireRole(ROLES.EDITOR, ROLES.ADMIN), controller.addItem);
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
const router = require("express").Router();
|
||||
const controller = require("../controllers/suggest.controller");
|
||||
const auth = require("../middleware/auth");
|
||||
const requireRole = require("../middleware/rbac");
|
||||
const { ROLES } = require("../models/user.model");
|
||||
|
||||
router.get("/", auth, requireRole(ROLES.VIEWER, ROLES.EDITOR, ROLES.ADMIN), controller.getHistory);
|
||||
|
||||
module.exports = router;
|
||||
@ -2,7 +2,6 @@ import api from "./axios";
|
||||
|
||||
export const loginRequest = async (username, password) => {
|
||||
const res = await api.post("/auth/login", { username, password });
|
||||
alert(`Response data: ${JSON.stringify(res.data)}`);
|
||||
return res.data;
|
||||
};
|
||||
|
||||
|
||||
@ -3,7 +3,4 @@ import api from "./axios";
|
||||
export const getList = () => api.get("/list");
|
||||
export const addItem = (itemName, quantiy) => api.post("/list/add", { itemName, quantiy });
|
||||
export const markBought = (id) => api.post("/list/mark-bought", { id });
|
||||
export const suggest = (query) => {
|
||||
console.log("API SUGGEST QUERY:", query);
|
||||
api.get("/suggest", { query });
|
||||
};
|
||||
export const getSuggestions = (query) => api.get("/list/suggest", { params: { query: query } });
|
||||
@ -2,4 +2,5 @@ export const ROLES = {
|
||||
VIEWER: "viewer",
|
||||
EDITOR: "editor",
|
||||
ADMIN: "admin",
|
||||
UP_TO_ADMIN: ["viewer", "editor", "admin"],
|
||||
};
|
||||
@ -1,5 +1,6 @@
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { addItem, getList, markBought, suggest } from "../api/list";
|
||||
import { addItem, getList, getSuggestions, markBought } from "../api/list";
|
||||
import { ROLES } from "../constants/roles";
|
||||
import { AuthContext } from "../context/AuthContext";
|
||||
import "../styles/GroceryList.css";
|
||||
|
||||
@ -56,7 +57,11 @@ export default function GroceryList() {
|
||||
}
|
||||
|
||||
try {
|
||||
setSuggestions(suggest(text).data.map((i) => i.item_name));
|
||||
console.log("Getting suggestions for:", text);
|
||||
let suggestions = await getSuggestions(text);
|
||||
suggestions = suggestions.data.map(s => s.item_name);
|
||||
console.log(`Suggestions: ${suggestions}`);
|
||||
setSuggestions(suggestions);
|
||||
} catch {
|
||||
setSuggestions([]);
|
||||
}
|
||||
@ -89,8 +94,7 @@ export default function GroceryList() {
|
||||
<div className="glist-body">
|
||||
<div className="glist-container">
|
||||
|
||||
<h1 className="glist-title">Costco Grocery List - {username}[{role}]</h1>
|
||||
<p><strong>{username}</strong> ({role})</p>
|
||||
<h1 className="glist-title">Costco Grocery List</h1>
|
||||
|
||||
{/* Sorting dropdown */}
|
||||
<select
|
||||
@ -105,7 +109,7 @@ export default function GroceryList() {
|
||||
</select>
|
||||
|
||||
{/* Add Item form (editor/admin only) */}
|
||||
{(role === "editor" || role === "admin") && showAddForm && (
|
||||
{[ROLES.ADMIN, ROLES.VIEWER].includes(role) && showAddForm && (
|
||||
<>
|
||||
<input
|
||||
type="text"
|
||||
@ -163,7 +167,7 @@ export default function GroceryList() {
|
||||
</div>
|
||||
|
||||
{/* Floating Button (editor/admin only) */}
|
||||
{(role === "editor" || role === "admin") && (
|
||||
{[ROLES.ADMIN, ROLES.VIEWER].includes(role) && (
|
||||
<button
|
||||
className="glist-fab"
|
||||
onClick={() => setShowAddForm(!showAddForm)}
|
||||
|
||||
@ -16,7 +16,7 @@ export default function Login() {
|
||||
login(data);
|
||||
window.location.href = "/";
|
||||
} catch (err) {
|
||||
setError("Invalid username or password");
|
||||
setError(err.response?.data?.message || "Login failed");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -54,14 +54,18 @@
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
width: calc(100% - 2em);
|
||||
left: 1em;
|
||||
right: 1em;
|
||||
z-index: 999;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.08);
|
||||
padding: 1em;
|
||||
width: calc(100% - 8em);
|
||||
max-width: 440px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.glist-suggest-item {
|
||||
padding: 0.5em;
|
||||
padding-inline: 2em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user