Skip to content

Commit

Permalink
Merge pull request #25 from atlp-rwanda/187788643-category-crud-opera…
Browse files Browse the repository at this point in the history
…tion

[#finishes] Feature for Implementing category CRUD operation
  • Loading branch information
niyontwali authored and gracemugwanezak committed Jul 10, 2024
2 parents b333734 + b45c3ba commit 738d896
Show file tree
Hide file tree
Showing 35 changed files with 1,144 additions and 376 deletions.
33 changes: 30 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@ import Success from './components/authentication/Success';
import RegisterSection from './components/authentication/RegisterSection';
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import Login from './pages/Login';
import EditUserProfile from './pages/EditUserProfile';
import LandingPage from './pages/LandingPage';
import GoogleAuthSuccess from './components/authentication/GoogleAuthSucces';
import { ToastContainer } from 'react-toastify';
import AdminPage from './pages/Admin';
import Category from './pages/Admin/Category';
import Searchpage from './containers/searchResults/SearchPage';
import { useDispatch } from 'react-redux';
import { ProductResponse, Product } from './types/Types';
import { useEffect, useRef } from 'react';
import { useGetProductsQuery } from './services/productApi';
import { setError, setIsLoading, setProductFetched, setProductsDataList } from './redux/slices/productsSlice';
import RestrictedRoute from './components/dashboard/RestrictedRoute';
import AdminPage from './pages/admin';
import Category from './pages/admin/Category';
import Sellers from './pages/admin/Sellers';
import Buyers from './pages/admin/Buyers';
import Messages from './pages/admin/Messages';
import Settings from './pages/admin/Settings';

const App = () => {
const { data, error, isLoading } = useGetProductsQuery();
const dispatch = useDispatch();
Expand Down Expand Up @@ -59,6 +66,10 @@ const App = () => {
path: 'auth/success/:token',
element: <GoogleAuthSuccess />,
},
{
path: 'profile',
element: <EditUserProfile />,
},
],
},
{
Expand All @@ -74,7 +85,7 @@ const App = () => {
},
{
path: 'admin',
element: <AdminPage />,
element: <RestrictedRoute role='admin' />,
children: [
{
index: true,
Expand All @@ -84,6 +95,22 @@ const App = () => {
path: 'categories',
element: <Category />,
},
{
path: 'sellers',
element: <Sellers />,
},
{
path: 'buyers',
element: <Buyers />,
},
{
path: 'messages',
element: <Messages />,
},
{
path: 'settings',
element: <Settings />,
},
],
},
{
Expand Down
Binary file added src/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 0 additions & 23 deletions src/components/SampleComponent.tsx

This file was deleted.

85 changes: 0 additions & 85 deletions src/components/Sidebar.tsx

This file was deleted.

46 changes: 30 additions & 16 deletions src/components/authentication/LoginComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,44 @@ import Input from '../common/Input';
import { loginSchema, LoginData } from '../../utils/schemas';
import { useNavigate, useLocation, useSearchParams } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import { setToken, setUser } from '../../redux/slices/userSlice';
import { setToken, setUser, setRole } from '../../redux/slices/userSlice';
import { useLoginUserMutation } from '../../services/authAPI';
import handleGoogleAuthentication from '../../utils/handleGoogleAuthentication';
import { Bounce, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { CustomJwtPayload } from '../../types/Types';
import { RootState } from '../../redux/store';
import { useGetUserByIdQuery } from '../../services/userApi';

const LoginComponent = () => {
const navigate = useNavigate();
const location = useLocation();
const dispatch = useDispatch();
const [searchParams, setSearchParams] = useSearchParams();
const isAuthenticated = useSelector((state: any) => state.user.token);

const isAuthenticated = useSelector((state: RootState) => state.user.token);
const userId = useSelector((state: RootState) => state.user.userId);
const {
register,
handleSubmit,
setError,
formState: { errors, isSubmitting },
} = useForm<LoginData>({ resolver: zodResolver(loginSchema) });

const [loginUser, { data, error, isLoading, isSuccess, isError }] = useLoginUserMutation();
const [loginUser, { data: loginData, error, isLoading, isSuccess: isLoginSuccess, isError }] = useLoginUserMutation();

const { data: userData, isSuccess: isUserSuccess } = useGetUserByIdQuery(userId);

useEffect(() => {
if (isAuthenticated) {
navigate('/');
}
if (isError && error) {
setError('root', {
message: 'Invalid email or password',
});
}

if (isSuccess && data) {
const token = data.token;
if (isLoginSuccess && loginData.ok) {
const token: string = loginData.token;
dispatch(setToken(token));
const decodedToken = jwtDecode<CustomJwtPayload>(token);
dispatch(setUser(decodedToken.id));

const from = location.state?.from?.pathname || '/';
navigate(from);
}
const message = searchParams.get('message');
if (message) {
Expand All @@ -66,17 +64,33 @@ const LoginComponent = () => {
}, [
isError,
isAuthenticated,
isSuccess,
isLoginSuccess,
error,
data,
loginData,
searchParams,
setSearchParams,
navigate,
location.state,
dispatch,
setError,
userId,
]);

useEffect(() => {
if (isUserSuccess && userData) {
const role = userData.message.Role.name;
dispatch(setRole(role));
if (role === 'buyer' && isAuthenticated) {
const from = location.state?.from?.pathname || '/';
navigate(from);
} else if (role === 'admin') {
navigate('/admin');
} else {
navigate('seller');
}
}
}, [isUserSuccess, userData]);

const onSubmit: SubmitHandler<LoginData> = async userCredentials => {
await loginUser(userCredentials);
};
Expand Down Expand Up @@ -113,7 +127,7 @@ const LoginComponent = () => {
>
{isSubmitting || isLoading ? 'Loading...' : 'Sign In'}
</button>
{isSuccess && <p className='text-green-600 text-xs font-normal'>Login successful!</p>}
{isLoginSuccess && <p className='text-green-600 text-xs font-normal'>Login successful!</p>}
<span className='self-center font-bold text-grayColor'>or</span>
<button
onClick={handleGoogleAuthentication}
Expand Down
9 changes: 7 additions & 2 deletions src/components/common/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { cn } from '../../utils';

interface InputProps {
type: string;
label: string;
label?: string;
id: string;
placeholder: string;
error?: string;
Expand All @@ -21,7 +21,10 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
type={type}
id={id}
placeholder={placeholder}
className={cn('p-1 px-3 rounded-lg border border-blackColor outline-none font-normal', inputClasname)}
className={cn(
'p-1 px-3 rounded-lg border border-blackColor outline-none font-normal disabled:cursor-not-allowed disabled:opacity-50 focus:ring-grayColor/40 disabled:border-grayColor',
inputClasname
)}
ref={ref}
{...rest}
/>
Expand All @@ -31,4 +34,6 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
}
);

Input.displayName = 'Input';

export default Input;
Loading

0 comments on commit 738d896

Please sign in to comment.