Improved the whole user usage
This commit is contained in:
@@ -43,7 +43,7 @@ export default function Navbar({profilePicture, timer, showExamEnd = false}: Pro
|
|||||||
items: [
|
items: [
|
||||||
{label: "List", icon: "pi pi-fw pi-users", url: "/users"},
|
{label: "List", icon: "pi pi-fw pi-users", url: "/users"},
|
||||||
{label: "Stats", icon: "pi pi-fw pi-chart-pie", url: "/stats"},
|
{label: "Stats", icon: "pi pi-fw pi-chart-pie", url: "/stats"},
|
||||||
{label: "History", icon: "pi pi-fw pi-chart-pie", url: "/history"},
|
{label: "History", icon: "pi pi-fw pi-history", url: "/history"},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,15 +7,12 @@ import axios from "axios";
|
|||||||
const fetcher = (url: string) => axios.get(url).then((res) => res.data);
|
const fetcher = (url: string) => axios.get(url).then((res) => res.data);
|
||||||
|
|
||||||
export default function useUser({redirectTo = "", redirectIfFound = false} = {}) {
|
export default function useUser({redirectTo = "", redirectIfFound = false} = {}) {
|
||||||
const {data: user, mutate: mutateUser, isLoading} = useSWR<User>("/api/user", fetcher);
|
const {data: user, mutate: mutateUser, isLoading, error} = useSWR<User>("/api/user", fetcher);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// if no redirect needed, just return (example: already on /dashboard)
|
// if no redirect needed, just return (example: already on /dashboard)
|
||||||
// if user data not yet there (fetch in progress, logged in or not) then don't do anything yet
|
// if user data not yet there (fetch in progress, logged in or not) then don't do anything yet
|
||||||
if (!redirectTo || !user) return;
|
if (!redirectTo || !user) return;
|
||||||
if (redirectTo && !user) {
|
|
||||||
Router.push(redirectTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
// If redirectTo is set, redirect if the user was not found.
|
// If redirectTo is set, redirect if the user was not found.
|
||||||
@@ -25,7 +22,7 @@ export default function useUser({redirectTo = "", redirectIfFound = false} = {})
|
|||||||
) {
|
) {
|
||||||
Router.push(redirectTo);
|
Router.push(redirectTo);
|
||||||
}
|
}
|
||||||
}, [user, redirectIfFound, redirectTo]);
|
}, [user, redirectIfFound, redirectTo, error]);
|
||||||
|
|
||||||
return {user, mutateUser, isLoading};
|
return {user, mutateUser, isLoading};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,16 +13,6 @@ export default withIronSessionApiRoute(user, sessionOptions);
|
|||||||
|
|
||||||
async function user(req: NextApiRequest, res: NextApiResponse) {
|
async function user(req: NextApiRequest, res: NextApiResponse) {
|
||||||
if (req.session.user) {
|
if (req.session.user) {
|
||||||
if (!auth.currentUser) {
|
|
||||||
res.status(401).json(undefined);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.session.user.id !== auth.currentUser.uid) {
|
|
||||||
res.status(401).json(undefined);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const docUser = await getDoc(doc(db, "users", req.session.user.id));
|
const docUser = await getDoc(doc(db, "users", req.session.user.id));
|
||||||
if (!docUser.exists()) {
|
if (!docUser.exists()) {
|
||||||
res.status(401).json(undefined);
|
res.status(401).json(undefined);
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ import {Divider} from "primereact/divider";
|
|||||||
import useUser from "@/hooks/useUser";
|
import useUser from "@/hooks/useUser";
|
||||||
import {Timeline} from "primereact/timeline";
|
import {Timeline} from "primereact/timeline";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import {AutoComplete} from "primereact/autocomplete";
|
||||||
|
import useUsers from "@/hooks/useUsers";
|
||||||
|
import {Dropdown} from "primereact/dropdown";
|
||||||
|
|
||||||
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
||||||
const user = req.session.user;
|
const user = req.session.user;
|
||||||
@@ -33,17 +36,18 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
|||||||
};
|
};
|
||||||
}, sessionOptions);
|
}, sessionOptions);
|
||||||
|
|
||||||
export default function History() {
|
export default function History({user}: {user: User}) {
|
||||||
|
const [selectedUser, setSelectedUser] = useState<User>(user);
|
||||||
const [groupedStats, setGroupedStats] = useState<{[key: string]: Stat[]}>();
|
const [groupedStats, setGroupedStats] = useState<{[key: string]: Stat[]}>();
|
||||||
|
|
||||||
const {stats, isLoading} = useStats();
|
const {users, isLoading: isUsersLoading} = useUsers();
|
||||||
const {user} = useUser({redirectTo: "/login"});
|
const {stats, isLoading: isStatsLoading} = useStats(selectedUser?.id);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (stats && !isLoading) {
|
if (stats && !isStatsLoading) {
|
||||||
setGroupedStats(groupByDate(stats));
|
setGroupedStats(groupByDate(stats));
|
||||||
}
|
}
|
||||||
}, [stats, isLoading]);
|
}, [stats, isStatsLoading]);
|
||||||
|
|
||||||
const formatTimestamp = (timestamp: string) => {
|
const formatTimestamp = (timestamp: string) => {
|
||||||
const date = moment(parseInt(timestamp));
|
const date = moment(parseInt(timestamp));
|
||||||
@@ -62,7 +66,7 @@ export default function History() {
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<span>{formatTimestamp(timestamp)}</span>
|
<span>{formatTimestamp(timestamp)}</span>
|
||||||
<div className="bg-white p-4 rounded-xl mb-4 flex flex-col gap-2">
|
<div className="bg-white p-4 rounded-xl mb-4 flex flex-col gap-2 drop-shadow-lg">
|
||||||
<span>
|
<span>
|
||||||
Modules:{" "}
|
Modules:{" "}
|
||||||
{formatModuleTotalStats(dateStats)
|
{formatModuleTotalStats(dateStats)
|
||||||
@@ -89,18 +93,17 @@ export default function History() {
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
{user && (
|
<main className="w-full h-full min-h-[100vh] flex flex-col bg-neutral-100 text-black">
|
||||||
<main className="w-full h-full min-h-[100vh] flex flex-col items-center bg-neutral-100 text-black">
|
|
||||||
<Navbar profilePicture={user.profilePicture} />
|
<Navbar profilePicture={user.profilePicture} />
|
||||||
<div className="w-full h-full p-4 relative flex flex-col gap-8">
|
<div className="w-fit self-center">
|
||||||
{groupedStats && !isLoading && (
|
{!isUsersLoading && (
|
||||||
<div className="flex gap-4">
|
<Dropdown value={selectedUser} options={users} optionLabel="name" onChange={(e) => setSelectedUser(e.target.value)} />
|
||||||
<Timeline value={Object.keys(groupedStats)} content={customContent} />
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="w-2/3 h-full p-4 relative flex flex-col gap-8">
|
||||||
|
{groupedStats && !isStatsLoading && <Timeline value={Object.keys(groupedStats)} content={customContent} />}
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ export default function Stats({user}: {user: User}) {
|
|||||||
const {users, isLoading} = useUsers();
|
const {users, isLoading} = useUsers();
|
||||||
const {stats, isLoading: isStatsLoading} = useStats(selectedUser?.id);
|
const {stats, isLoading: isStatsLoading} = useStats(selectedUser?.id);
|
||||||
|
|
||||||
useEffect(() => console.log({stats}), [stats]);
|
|
||||||
|
|
||||||
const search = (event: {query: string}) => {
|
const search = (event: {query: string}) => {
|
||||||
setItems(event.query ? users.filter((x) => x.name.startsWith(event.query)) : users);
|
setItems(event.query ? users.filter((x) => x.name.startsWith(event.query)) : users);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user