mirror of
https://github.com/cheveguerra/whaticket-community.git
synced 2026-04-20 04:39:20 +00:00
improvement: adopted infinity scroll in users and contacts
This commit is contained in:
@@ -7,7 +7,7 @@ const User = require("../models/User");
|
|||||||
const { getIO } = require("../libs/socket");
|
const { getIO } = require("../libs/socket");
|
||||||
|
|
||||||
exports.index = async (req, res) => {
|
exports.index = async (req, res) => {
|
||||||
const { searchParam = "", pageNumber = 1, rowsPerPage = 10 } = req.query;
|
const { searchParam = "", pageNumber = 1 } = req.query;
|
||||||
|
|
||||||
const whereCondition = {
|
const whereCondition = {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
@@ -22,7 +22,7 @@ exports.index = async (req, res) => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
let limit = +rowsPerPage;
|
let limit = 20;
|
||||||
let offset = limit * (pageNumber - 1);
|
let offset = limit * (pageNumber - 1);
|
||||||
|
|
||||||
const { count, rows: users } = await User.findAndCountAll({
|
const { count, rows: users } = await User.findAndCountAll({
|
||||||
@@ -33,7 +33,9 @@ exports.index = async (req, res) => {
|
|||||||
order: [["createdAt", "DESC"]],
|
order: [["createdAt", "DESC"]],
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).json({ users, count });
|
const hasMore = count > offset + users.length;
|
||||||
|
|
||||||
|
return res.status(200).json({ users, count, hasMore });
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.store = async (req, res, next) => {
|
exports.store = async (req, res, next) => {
|
||||||
|
|||||||
@@ -47,25 +47,22 @@ const reducer = (state, action) => {
|
|||||||
return [...state, ...newContacts];
|
return [...state, ...newContacts];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "UPDATE_CONTACT") {
|
if (action.type === "UPDATE_CONTACTS") {
|
||||||
const updatedContact = action.payload;
|
const contact = action.payload;
|
||||||
const contactIndex = state.findIndex(c => c.id === updatedContact.id);
|
const contactIndex = state.findIndex(c => c.id === contact.id);
|
||||||
|
|
||||||
if (contactIndex !== -1) {
|
if (contactIndex !== -1) {
|
||||||
state[contactIndex] = updatedContact;
|
state[contactIndex] = contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...state];
|
return [contact, ...state];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "DELETE_CONTACT") {
|
if (action.type === "DELETE_CONTACT") {
|
||||||
const contactId = action.payload;
|
const contactId = action.payload;
|
||||||
console.log("cai aqui", contactId);
|
|
||||||
|
|
||||||
const contactIndex = state.findIndex(c => c.id === contactId);
|
const contactIndex = state.findIndex(c => c.id === contactId);
|
||||||
if (contactIndex !== -1) {
|
if (contactIndex !== -1) {
|
||||||
console.log("cai no if");
|
|
||||||
|
|
||||||
state.splice(contactIndex, 1);
|
state.splice(contactIndex, 1);
|
||||||
}
|
}
|
||||||
return [...state];
|
return [...state];
|
||||||
@@ -119,7 +116,7 @@ const Contacts = () => {
|
|||||||
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
|
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
|
||||||
socket.on("contact", data => {
|
socket.on("contact", data => {
|
||||||
if (data.action === "update" || data.action === "create") {
|
if (data.action === "update" || data.action === "create") {
|
||||||
dispatch({ type: "UPDATE_CONTACT", payload: data.contact });
|
dispatch({ type: "UPDATE_CONTACTS", payload: data.contact });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.action === "delete") {
|
if (data.action === "delete") {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useReducer } from "react";
|
||||||
|
|
||||||
import openSocket from "socket.io-client";
|
import openSocket from "socket.io-client";
|
||||||
|
|
||||||
@@ -28,6 +28,45 @@ import TableRowSkeleton from "../../components/TableRowSkeleton";
|
|||||||
import UserModal from "../../components/UserModal";
|
import UserModal from "../../components/UserModal";
|
||||||
import ConfirmationModal from "../../components/ConfirmationModal";
|
import ConfirmationModal from "../../components/ConfirmationModal";
|
||||||
|
|
||||||
|
const reducer = (state, action) => {
|
||||||
|
if (action.type === "LOAD_USERS") {
|
||||||
|
const users = action.payload;
|
||||||
|
const newUsers = [];
|
||||||
|
|
||||||
|
users.forEach(user => {
|
||||||
|
const userIndex = state.findIndex(u => u.id === user.id);
|
||||||
|
if (userIndex !== -1) {
|
||||||
|
state[userIndex] = user;
|
||||||
|
} else {
|
||||||
|
newUsers.push(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return [...state, ...newUsers];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.type === "UPDATE_USERS") {
|
||||||
|
const user = action.payload;
|
||||||
|
const userIndex = state.findIndex(u => u.id === user.id);
|
||||||
|
|
||||||
|
if (userIndex !== -1) {
|
||||||
|
state[userIndex] = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [user, ...state];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.type === "DELETE_USER") {
|
||||||
|
const userId = action.payload;
|
||||||
|
|
||||||
|
const userIndex = state.findIndex(u => u.id === userId);
|
||||||
|
if (userIndex !== -1) {
|
||||||
|
state.splice(userIndex, 1);
|
||||||
|
}
|
||||||
|
return [...state];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
mainPaper: {
|
mainPaper: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@@ -42,22 +81,24 @@ const Users = () => {
|
|||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [pageNumber, setPageNumber] = useState(1);
|
const [pageNumber, setPageNumber] = useState(1);
|
||||||
|
const [hasMore, setHasMore] = useState(false);
|
||||||
const [selectedUserId, setSelectedUserId] = useState(null);
|
const [selectedUserId, setSelectedUserId] = useState(null);
|
||||||
const [userModalOpen, setUserModalOpen] = useState(false);
|
const [userModalOpen, setUserModalOpen] = useState(false);
|
||||||
const [confirmModalOpen, setConfirmModalOpen] = useState(false);
|
const [confirmModalOpen, setConfirmModalOpen] = useState(false);
|
||||||
const [deletingUser, setDeletingUser] = useState(null);
|
const [deletingUser, setDeletingUser] = useState(null);
|
||||||
const [searchParam, setSearchParam] = useState("");
|
const [searchParam, setSearchParam] = useState("");
|
||||||
const [users, setUsers] = useState([]);
|
const [users, dispatch] = useReducer(reducer, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const delayDebounceFn = setTimeout(() => {
|
const delayDebounceFn = setTimeout(() => {
|
||||||
const fetchUsers = async () => {
|
const fetchUsers = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await api.get("/users/", {
|
const { data } = await api.get("/users/", {
|
||||||
params: { searchParam, pageNumber },
|
params: { searchParam, pageNumber },
|
||||||
});
|
});
|
||||||
setUsers(res.data.users);
|
dispatch({ type: "LOAD_USERS", payload: data.users });
|
||||||
|
setHasMore(data.hasMore);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -73,11 +114,11 @@ const Users = () => {
|
|||||||
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
|
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
|
||||||
socket.on("user", data => {
|
socket.on("user", data => {
|
||||||
if (data.action === "update" || data.action === "create") {
|
if (data.action === "update" || data.action === "create") {
|
||||||
updateUsers(data.user);
|
dispatch({ type: "UPDATE_USERS", payload: data.user });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.action === "delete") {
|
if (data.action === "delete") {
|
||||||
deleteUser(data.userId);
|
dispatch({ type: "DELETE_USER", payload: +data.userId });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,31 +127,6 @@ const Users = () => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const updateUsers = user => {
|
|
||||||
setUsers(prevState => {
|
|
||||||
const userIndex = prevState.findIndex(c => c.id === user.id);
|
|
||||||
|
|
||||||
if (userIndex === -1) {
|
|
||||||
return [user, ...prevState];
|
|
||||||
}
|
|
||||||
const aux = [...prevState];
|
|
||||||
aux[userIndex] = user;
|
|
||||||
return aux;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteUser = userId => {
|
|
||||||
setUsers(prevState => {
|
|
||||||
const userIndex = prevState.findIndex(c => c.id === +userId);
|
|
||||||
|
|
||||||
if (userIndex === -1) return prevState;
|
|
||||||
|
|
||||||
const aux = [...prevState];
|
|
||||||
aux.splice(userIndex, 1);
|
|
||||||
return aux;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleOpenUserModal = () => {
|
const handleOpenUserModal = () => {
|
||||||
setSelectedUserId(null);
|
setSelectedUserId(null);
|
||||||
setUserModalOpen(true);
|
setUserModalOpen(true);
|
||||||
@@ -141,6 +157,18 @@ const Users = () => {
|
|||||||
setPageNumber(1);
|
setPageNumber(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadMore = () => {
|
||||||
|
setPageNumber(prevState => prevState + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleScroll = e => {
|
||||||
|
if (!hasMore || loading) return;
|
||||||
|
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
|
||||||
|
if (scrollHeight - (scrollTop + 100) < clientHeight) {
|
||||||
|
loadMore();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MainContainer>
|
<MainContainer>
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
@@ -182,7 +210,11 @@ const Users = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</MainHeaderButtonsWrapper>
|
</MainHeaderButtonsWrapper>
|
||||||
</MainHeader>
|
</MainHeader>
|
||||||
<Paper className={classes.mainPaper} variant="outlined">
|
<Paper
|
||||||
|
className={classes.mainPaper}
|
||||||
|
variant="outlined"
|
||||||
|
onScroll={handleScroll}
|
||||||
|
>
|
||||||
<Table size="small">
|
<Table size="small">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
|||||||
Reference in New Issue
Block a user