mirror of
https://github.com/cheveguerra/whaticket-community.git
synced 2026-04-17 19:37:02 +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");
|
||||
|
||||
exports.index = async (req, res) => {
|
||||
const { searchParam = "", pageNumber = 1, rowsPerPage = 10 } = req.query;
|
||||
const { searchParam = "", pageNumber = 1 } = req.query;
|
||||
|
||||
const whereCondition = {
|
||||
[Op.or]: [
|
||||
@@ -22,7 +22,7 @@ exports.index = async (req, res) => {
|
||||
],
|
||||
};
|
||||
|
||||
let limit = +rowsPerPage;
|
||||
let limit = 20;
|
||||
let offset = limit * (pageNumber - 1);
|
||||
|
||||
const { count, rows: users } = await User.findAndCountAll({
|
||||
@@ -33,7 +33,9 @@ exports.index = async (req, res) => {
|
||||
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) => {
|
||||
|
||||
@@ -47,25 +47,22 @@ const reducer = (state, action) => {
|
||||
return [...state, ...newContacts];
|
||||
}
|
||||
|
||||
if (action.type === "UPDATE_CONTACT") {
|
||||
const updatedContact = action.payload;
|
||||
const contactIndex = state.findIndex(c => c.id === updatedContact.id);
|
||||
if (action.type === "UPDATE_CONTACTS") {
|
||||
const contact = action.payload;
|
||||
const contactIndex = state.findIndex(c => c.id === contact.id);
|
||||
|
||||
if (contactIndex !== -1) {
|
||||
state[contactIndex] = updatedContact;
|
||||
state[contactIndex] = contact;
|
||||
}
|
||||
|
||||
return [...state];
|
||||
return [contact, ...state];
|
||||
}
|
||||
|
||||
if (action.type === "DELETE_CONTACT") {
|
||||
const contactId = action.payload;
|
||||
console.log("cai aqui", contactId);
|
||||
|
||||
const contactIndex = state.findIndex(c => c.id === contactId);
|
||||
if (contactIndex !== -1) {
|
||||
console.log("cai no if");
|
||||
|
||||
state.splice(contactIndex, 1);
|
||||
}
|
||||
return [...state];
|
||||
@@ -119,7 +116,7 @@ const Contacts = () => {
|
||||
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
|
||||
socket.on("contact", data => {
|
||||
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") {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useReducer } from "react";
|
||||
|
||||
import openSocket from "socket.io-client";
|
||||
|
||||
@@ -28,6 +28,45 @@ import TableRowSkeleton from "../../components/TableRowSkeleton";
|
||||
import UserModal from "../../components/UserModal";
|
||||
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 => ({
|
||||
mainPaper: {
|
||||
flex: 1,
|
||||
@@ -42,22 +81,24 @@ const Users = () => {
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [pageNumber, setPageNumber] = useState(1);
|
||||
const [hasMore, setHasMore] = useState(false);
|
||||
const [selectedUserId, setSelectedUserId] = useState(null);
|
||||
const [userModalOpen, setUserModalOpen] = useState(false);
|
||||
const [confirmModalOpen, setConfirmModalOpen] = useState(false);
|
||||
const [deletingUser, setDeletingUser] = useState(null);
|
||||
const [searchParam, setSearchParam] = useState("");
|
||||
const [users, setUsers] = useState([]);
|
||||
const [users, dispatch] = useReducer(reducer, []);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
const delayDebounceFn = setTimeout(() => {
|
||||
const fetchUsers = async () => {
|
||||
try {
|
||||
const res = await api.get("/users/", {
|
||||
const { data } = await api.get("/users/", {
|
||||
params: { searchParam, pageNumber },
|
||||
});
|
||||
setUsers(res.data.users);
|
||||
dispatch({ type: "LOAD_USERS", payload: data.users });
|
||||
setHasMore(data.hasMore);
|
||||
setLoading(false);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
@@ -73,11 +114,11 @@ const Users = () => {
|
||||
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
|
||||
socket.on("user", data => {
|
||||
if (data.action === "update" || data.action === "create") {
|
||||
updateUsers(data.user);
|
||||
dispatch({ type: "UPDATE_USERS", payload: data.user });
|
||||
}
|
||||
|
||||
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 = () => {
|
||||
setSelectedUserId(null);
|
||||
setUserModalOpen(true);
|
||||
@@ -141,6 +157,18 @@ const Users = () => {
|
||||
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 (
|
||||
<MainContainer>
|
||||
<ConfirmationModal
|
||||
@@ -182,7 +210,11 @@ const Users = () => {
|
||||
</Button>
|
||||
</MainHeaderButtonsWrapper>
|
||||
</MainHeader>
|
||||
<Paper className={classes.mainPaper} variant="outlined">
|
||||
<Paper
|
||||
className={classes.mainPaper}
|
||||
variant="outlined"
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
<Table size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
|
||||
Reference in New Issue
Block a user