Added Polls Page
This commit is contained in:
@@ -13,6 +13,7 @@ import { QueryClient, QueryClientProvider } from "react-query";
|
||||
import PrivateRoute from "./components/PrivateRoute/PrivateRoute";
|
||||
import { ToastContainer } from "react-toastify";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
import Polls from "./pages/Polls";
|
||||
|
||||
function App() {
|
||||
const queryClient = new QueryClient();
|
||||
@@ -25,6 +26,7 @@ function App() {
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="/poll" element={<Polls />} />
|
||||
<Route element={<PrivateRoute />}>
|
||||
<Route path="dashboard" element={<Dashboard />} />
|
||||
<Route path="bookmark" element={<Bookmark />} />
|
||||
|
||||
@@ -1,26 +1,37 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import useUserStore from '../../store/useStore'
|
||||
import ProfileImage from './ProfileImage';
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import useUserStore from "../../store/useStore";
|
||||
import ProfileImage from "./ProfileImage";
|
||||
|
||||
function Header() {
|
||||
|
||||
const { user } = useUserStore();
|
||||
|
||||
return (
|
||||
<div className="navbar bg-base-100">
|
||||
<div className="flex-1">
|
||||
<Link to={"/"} className="btn btn-ghost text-xl">LivePoll</Link>
|
||||
<Link to={"/"} className="btn btn-ghost text-xl">
|
||||
LivePoll
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<ul className="menu menu-horizontal px-1">
|
||||
{user.username ? <li><Link to={"/dashboard"}>Dashboard</Link></li> : <li><Link to={"/login"}>Login</Link></li>}
|
||||
<li><Link to={'/bookmark'}>Bookmarks</Link></li>
|
||||
<ul className="menu menu-horizontal px-1 gap-1">
|
||||
{user.username ? (
|
||||
<li>
|
||||
<Link to={"/dashboard"}>Dashboard</Link>
|
||||
</li>
|
||||
) : (
|
||||
<li>
|
||||
<Link to={"/login"}>Login</Link>
|
||||
</li>
|
||||
)}
|
||||
<li>
|
||||
<Link to={"/poll"}>Polls</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{user.username && <ProfileImage userData={user} />}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default Header
|
||||
export default Header;
|
||||
|
||||
@@ -29,6 +29,9 @@ function ProfileImage({userData}) {
|
||||
Profile
|
||||
<span className="badge">New</span>
|
||||
</Link>
|
||||
<Link to={"/bookmark"} className="justify-between" >
|
||||
Bookmarks
|
||||
</Link>
|
||||
</li>
|
||||
<li><a onClick={handleLogout}>Logout</a></li>
|
||||
</ul>
|
||||
|
||||
28
frontend/src/components/PollCard/PollCard.jsx
Normal file
28
frontend/src/components/PollCard/PollCard.jsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
function PollCard({ poll }) {
|
||||
|
||||
const navigator = useNavigate();
|
||||
|
||||
const handleViewOnClick = () => {
|
||||
navigator(`/view/${poll._id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="card bg-base-300 shadow-xl text-white w-full md:w-80">
|
||||
<div className="card-body">
|
||||
<h2 className="card-title text-xl font-bold">{poll.title}</h2>
|
||||
<p className="text-sm text-base-content">{poll.description}</p>
|
||||
<div className="flex items-center justify-between mt-4">
|
||||
<div className="text-xs text-gray-400">
|
||||
Created by <span className="text-yellow-400">{poll.creatorData.username}</span> on {new Date(poll?.createdAt).toLocaleDateString()}
|
||||
</div>
|
||||
<button onClick={handleViewOnClick} className="btn btn-primary btn-sm text-base-content">View</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default PollCard;
|
||||
38
frontend/src/pages/Polls.jsx
Normal file
38
frontend/src/pages/Polls.jsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import React, { useState } from 'react'
|
||||
import { useQuery } from 'react-query'
|
||||
import getPollsService from '../services/getPollsService'
|
||||
import PollCard from '../components/PollCard/PollCard'
|
||||
import ErrorFallback from '../components/Errors/ErrorFallback'
|
||||
|
||||
function Polls() {
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
const [limit, setLimit] = useState(6);
|
||||
|
||||
const {data, isLoading, isError, isSuccess, refetch} = useQuery(["polls", page, limit], () => getPollsService(page, limit), {
|
||||
cacheTime: 1000 * 60 * 5, // 5 minutes
|
||||
staleTime: 1000 * 60 * 10, // 10 minutes
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="container mx-auto p-4 bg-base-200">
|
||||
<h1 className="text-2xl font-bold text-center mb-6">Polls</h1>
|
||||
{isSuccess && <div className="flex flex-wrap justify-center gap-6">
|
||||
{data?.data?.polls?.map((poll) => (
|
||||
<PollCard key={poll._id} poll={poll} />
|
||||
))}
|
||||
</div>}
|
||||
{isLoading && <div className='flex flex-wrap justify-center gap-6 skeleton min-h-40'></div>}
|
||||
{isError && <div className='flex justify-center gap-6'>
|
||||
<ErrorFallback onRetry={() => refetch()} />
|
||||
</div>}
|
||||
|
||||
<div className='flex justify-center gap-6 mt-6'>
|
||||
<button className='btn btn-primary btn-circle' disabled={page <= 1} onClick={() => setPage(page - 1)}>Prev</button>
|
||||
<button className='btn btn-primary btn-circle' disabled={data?.data?.totalPages === page} onClick={() => setPage(page + 1)}>Next</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Polls
|
||||
8
frontend/src/services/getPollsService.js
Normal file
8
frontend/src/services/getPollsService.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import axiosInstance from "../helper/axiosInstance";
|
||||
|
||||
async function getPollsService(page = 1, limit = 10) {
|
||||
const response = await axiosInstance.get(`poll/all?page=${page}&limit=${limit}`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export default getPollsService;
|
||||
Reference in New Issue
Block a user