|
1 | | -import { useParams } from 'react-router'; |
| 1 | +import { useEffect, useState, useRef } from 'react'; |
| 2 | +import { useParams, useNavigate, Link } from 'react-router'; |
| 3 | +import { useUser } from '../hooks/useUser'; |
| 4 | +import { useApi } from '../hooks/useApi'; |
| 5 | +import Spinny from '../components/Spinny'; |
| 6 | + |
2 | 7 | const UserPage = () => { |
3 | | - const { id } = useParams(); // Get the user ID from the URL |
| 8 | + const { id } = useParams(); |
| 9 | + const navigate = useNavigate(); |
| 10 | + const { isLogged, isAdmin } = useUser(); |
| 11 | + const [userData, setUserData] = useState(null); |
| 12 | + const [showDeactivateModal, setShowDeactivateModal] = useState(false); |
| 13 | + const deactivateModalRef = useRef(null); |
| 14 | + |
| 15 | + const { |
| 16 | + data: fetchUserData, |
| 17 | + error: fetchUserError, |
| 18 | + isLoading: isUserLoading, |
| 19 | + fetchFromApi: fetchUser, |
| 20 | + } = useApi(); |
| 21 | + |
| 22 | + const { |
| 23 | + data: updateUserData, |
| 24 | + error: updateError, |
| 25 | + isLoading: isUpdating, |
| 26 | + fetchFromApi: updateUserStatus, |
| 27 | + } = useApi({ method: 'PATCH' }); |
| 28 | + |
| 29 | + useEffect(() => { |
| 30 | + if (!isLogged) { |
| 31 | + navigate('/login'); |
| 32 | + return; |
| 33 | + } |
| 34 | + if (!isAdmin) { |
| 35 | + navigate('/'); |
| 36 | + return; |
| 37 | + } |
| 38 | + |
| 39 | + if (id) { |
| 40 | + fetchUser(`/users/${id}`); |
| 41 | + } |
| 42 | + }, [id, isLogged, isAdmin, navigate, fetchUser]); |
| 43 | + |
| 44 | + useEffect(() => { |
| 45 | + if (fetchUserData && !fetchUserError) { |
| 46 | + setUserData(fetchUserData); |
| 47 | + } |
| 48 | + if (fetchUserError) { |
| 49 | + console.error('Error fetching user data:', fetchUserError); |
| 50 | + } |
| 51 | + }, [fetchUserData, fetchUserError]); |
| 52 | + |
| 53 | + useEffect(() => { |
| 54 | + if (updateUserData && !updateError) { |
| 55 | + console.log('User status updated:', updateUserData); |
| 56 | + closeDeactivateModal(); |
| 57 | + setUserData(prevData => ({ |
| 58 | + ...prevData, |
| 59 | + is_active: updateUserData.is_active, |
| 60 | + })); |
| 61 | + } |
| 62 | + if (updateError) { |
| 63 | + console.error('Error updating user status:', updateError); |
| 64 | + } |
| 65 | + }, [updateUserData, updateError, navigate]); |
| 66 | + |
| 67 | + const handleToggleStatusClick = () => { |
| 68 | + setShowDeactivateModal(true); |
| 69 | + if (deactivateModalRef.current) { |
| 70 | + deactivateModalRef.current.showModal(); |
| 71 | + } |
| 72 | + }; |
| 73 | + |
| 74 | + const confirmToggleStatus = () => { |
| 75 | + if (id && !isUpdating && userData) { |
| 76 | + const newStatus = !userData.is_active; |
| 77 | + updateUserStatus(`/users/${id}`, { |
| 78 | + headers: { 'content-type': 'application/json' }, |
| 79 | + body: JSON.stringify({ is_active: newStatus }), |
| 80 | + }); |
| 81 | + } |
| 82 | + }; |
| 83 | + |
| 84 | + const closeDeactivateModal = () => { |
| 85 | + setShowDeactivateModal(false); |
| 86 | + if (deactivateModalRef.current) { |
| 87 | + deactivateModalRef.current.close(); |
| 88 | + } |
| 89 | + }; |
| 90 | + |
| 91 | + if (isUserLoading) { |
| 92 | + return <Spinny />; |
| 93 | + } |
| 94 | + |
| 95 | + if (fetchUserError || !userData) { |
| 96 | + return ( |
| 97 | + <div className='section-card flex flex-col items-center justify-center min-h-[60vh]'> |
| 98 | + <h1 className='section-heading text-error'>Error</h1> |
| 99 | + <p className='text-lg text-gray-600 mb-8'> |
| 100 | + {fetchUserError?.message || |
| 101 | + 'Could not load user data or user not found.'} |
| 102 | + </p> |
| 103 | + <Link to='/users' className='animated-button'> |
| 104 | + Back to All Users |
| 105 | + </Link> |
| 106 | + </div> |
| 107 | + ); |
| 108 | + } |
| 109 | + |
| 110 | + const isUserActive = userData.is_active; |
| 111 | + const modalAction = isUserActive ? 'Deactivate' : 'Activate'; |
| 112 | + const modalTitle = `Confirm ${isUserActive ? 'Deactivation' : 'Activation'}`; |
| 113 | + const confirmButtonClass = isUserActive |
| 114 | + ? 'animated-button !bg-gradient-to-r from-red-500 to-red-700 hover:!from-red-600 hover:!to-red-800' |
| 115 | + : 'animated-button !bg-gradient-to-r from-green-500 to-green-700 hover:!from-green-600 hover:!to-green-800'; |
4 | 116 |
|
5 | 117 | return ( |
6 | | - <div className='section-card flex flex-col items-center justify-center min-h-[60vh]'> |
7 | | - <h1 className='section-heading'>User Profile: {id}</h1> |
8 | | - <p className='text-lg text-gray-600 mb-8'> |
9 | | - This page will display the profile for user with ID: {id}. |
10 | | - </p> |
| 118 | + <div className='section-card flex flex-col items-center min-h-[60vh]'> |
| 119 | + <h1 className='section-heading'>User Profile: {userData.name}</h1> |
| 120 | + <div className='w-full max-w-xl p-4 bg-base-200 rounded-lg shadow-md'> |
| 121 | + <p className='text-lg mb-2'> |
| 122 | + <strong>Username:</strong> {userData.username} |
| 123 | + </p> |
| 124 | + <p className='text-lg mb-2'> |
| 125 | + <strong>Name:</strong> {userData.name} |
| 126 | + </p> |
| 127 | + <p className='text-lg mb-4'> |
| 128 | + <strong>Admin:</strong> {userData.is_admin ? 'Yes' : 'No'} |
| 129 | + </p> |
| 130 | + <p className='text-lg mb-4'> |
| 131 | + <strong>Status:</strong> {isUserActive ? 'Active' : 'Inactive'} |
| 132 | + </p> |
| 133 | + |
| 134 | + <div className='flex flex-col sm:flex-row justify-center gap-4 mt-6'> |
| 135 | + <Link to={`/users/${id}/edit`} className='animated-button'> |
| 136 | + Edit User |
| 137 | + </Link> |
| 138 | + <Link to={`/users/${id}/ideas`} className='animated-button'> |
| 139 | + View All Ideas |
| 140 | + </Link> |
| 141 | + <button |
| 142 | + onClick={handleToggleStatusClick} |
| 143 | + disabled={isUpdating} |
| 144 | + className={confirmButtonClass} |
| 145 | + > |
| 146 | + {isUpdating ? 'Updating Status...' : `${modalAction} Account`} |
| 147 | + </button> |
| 148 | + </div> |
| 149 | + </div> |
| 150 | + |
| 151 | + <dialog |
| 152 | + ref={deactivateModalRef} |
| 153 | + className='modal' |
| 154 | + open={showDeactivateModal} |
| 155 | + > |
| 156 | + <div className='modal-box'> |
| 157 | + <h3 className='font-bold text-lg'>{modalTitle}</h3> |
| 158 | + <p className='py-4'>{`${modalAction} ${userData.name}'s account?`}</p> |
| 159 | + {updateError && ( |
| 160 | + <p className='text-error mb-4'>Error: {updateError.message}</p> |
| 161 | + )} |
| 162 | + <div className='modal-action'> |
| 163 | + <button |
| 164 | + className='animated-button mr-2' |
| 165 | + onClick={closeDeactivateModal} |
| 166 | + disabled={isUpdating} |
| 167 | + > |
| 168 | + Cancel |
| 169 | + </button> |
| 170 | + <button |
| 171 | + className={confirmButtonClass} |
| 172 | + onClick={confirmToggleStatus} |
| 173 | + disabled={isUpdating} |
| 174 | + > |
| 175 | + {isUpdating ? 'Confirming...' : `Confirm ${modalAction}`} |
| 176 | + </button> |
| 177 | + </div> |
| 178 | + </div> |
| 179 | + <form |
| 180 | + method='dialog' |
| 181 | + className='modal-backdrop' |
| 182 | + onClick={closeDeactivateModal} |
| 183 | + > |
| 184 | + <button>close</button> |
| 185 | + </form> |
| 186 | + </dialog> |
11 | 187 | </div> |
12 | 188 | ); |
13 | 189 | }; |
|
0 commit comments