Update Profile.tsx

This commit is contained in:
Aryan Jain
2025-05-29 23:29:48 +05:30
committed by GitHub
parent 66cee50a6c
commit e3b8b49dc4

View File

@ -1,6 +1,5 @@
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@ -11,24 +10,27 @@ import {
ListItem, ListItem,
Typography, Typography,
LinearProgress, LinearProgress,
Button,
} from '@mui/material'; } from '@mui/material';
import BoltIcon from '@mui/icons-material/Bolt'; import BoltIcon from '@mui/icons-material/Bolt';
import RedeemIcon from '@mui/icons-material/Redeem';
import RobotAvatar from '../RobotAvatar'; import RobotAvatar from '../RobotAvatar';
import RobotInfo from '../RobotInfo'; import RobotInfo from '../RobotInfo';
import { FederationContext, type UseFederationStoreType } from '../../contexts/FederationContext'; import { FederationContext, type UseFederationStoreType } from '../../contexts/FederationContext';
import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext'; import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext';
import { type Coordinator } from '../../models'; import { type Coordinator } from '../../models';
import ClaimRewardDialog from './ClaimRewardDialog'; // New import
interface Props { interface Props {
open: boolean; open: boolean;
onClose: () => void; onClose: () => void;
} }
const ProfileDialog = ({ open = false, onClose }: Props): React.JSX.Element => { const ProfileDialog = ({ open = false, onClose }: Props): JSX.Element => {
const { federation } = useContext<UseFederationStoreType>(FederationContext); const { federation } = useContext<UseFederationStoreType>(FederationContext);
const { garage, slotUpdatedAt } = useContext<UseGarageStoreType>(GarageContext); const { garage, slotUpdatedAt } = useContext<UseGarageStoreType>(GarageContext);
const { t } = useTranslation(); const { t } = useTranslation();
const [isClaimRewardDialogOpen, setIsClaimRewardDialogOpen] = useState<boolean>(false);
const slot = garage.getSlot(); const slot = garage.getSlot();
@ -42,87 +44,157 @@ const ProfileDialog = ({ open = false, onClose }: Props): React.JSX.Element => {
setLoadingRobots(Object.values(slot?.robots ?? {}).filter((robot) => robot.loading).length); setLoadingRobots(Object.values(slot?.robots ?? {}).filter((robot) => robot.loading).length);
}, [slotUpdatedAt]); }, [slotUpdatedAt]);
return ( const handleClaimReward = () => {
<Dialog setIsClaimRewardDialogOpen(true);
open={open} };
onClose={onClose}
aria-labelledby='profile-title'
aria-describedby='profile-description'
>
<div style={loading ? {} : { display: 'none' }}>
<LinearProgress />
</div>
<DialogContent>
<Typography component='h5' variant='h5'>
{t('Your Robot')}
</Typography>
<List>
<Divider />
<ListItem className='profileNickname'> const handleCloseClaimRewardDialog = () => {
<ListItemText> setIsClaimRewardDialogOpen(false);
<Typography component='h6' variant='h6'> };
{!garage.getSlot()?.nickname && (
<div style={{ position: 'relative', left: '-7px' }}> // Determine if there are any rewards to claim
const hasClaimableRewards = federation.getCoordinators().some((coordinator: Coordinator) => {
const coordinatorRobot = garage.getSlot()?.getRobot(coordinator.shortAlias);
// Assuming 'earnedRewards' property exists on the robot object
return coordinatorRobot && coordinatorRobot.earnedRewards > 0;
});
return (
<>
<Dialog
open={open}
onClose={onClose}
aria-labelledby="profile-title"
aria-describedby="profile-description"
sx={{ '& .MuiDialog-paper': { minWidth: '300px', maxWidth: '500px', borderRadius: '8px' } }}
>
<div style={{ display: loading ? 'block' : 'none', padding: '0' }}>
<LinearProgress sx={{ height: '6px', borderRadius: '4px' }} />
</div>
<DialogContent sx={{ padding: '20px' }}>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: '16px',
}}
>
<Typography variant="h5" sx={{ fontWeight: 600, color: '#333' }}>
{t('Your Robot')}
</Typography>
<Button
variant="contained"
color="primary"
startIcon={<RedeemIcon />}
onClick={handleClaimReward}
disabled={!hasClaimableRewards} // Button is disabled if no rewards to claim
sx={{
borderRadius: '20px',
textTransform: 'none',
padding: '6px 16px',
fontWeight: 500,
backgroundColor: '#1976d2', // Default primary color
'&:hover': { backgroundColor: '#1565c0' },
}}
>
{t('Claim Reward')}
</Button>
</div>
<List sx={{ padding: 0 }}>
<Divider sx={{ margin: '12px 0', backgroundColor: '#e0e0e0' }} />
<ListItem
sx={{
padding: '12px 0',
alignItems: 'center',
'&:hover': { backgroundColor: '#f5f5f5', borderRadius: '4px' },
}}
>
<ListItemText>
<Typography variant="h6" sx={{ fontWeight: 500, color: '#555' }}>
{garage.getSlot()?.nickname ? (
<div <div
style={{ style={{
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'left', gap: '8px',
flexWrap: 'wrap', flexWrap: 'wrap',
width: 300,
}} }}
> >
<BoltIcon sx={{ color: '#fcba03', height: '28px', width: '24px' }} /> <BoltIcon sx={{ color: '#fcba03', height: '24px', width: '24px' }} />
<span style={{ color: '#333', fontSize: '1.25rem' }}>
<a>{garage.getSlot()?.nickname}</a> {garage.getSlot()?.nickname}
</span>
<BoltIcon sx={{ color: '#fcba03', height: '28px', width: '24px' }} /> <BoltIcon sx={{ color: '#fcba03', height: '24px', width: '24px' }} />
</div> </div>
) : (
<span style={{ color: '#888', fontStyle: 'italic' }}>{t('No nickname set')}</span>
)}
</Typography>
{loadingRobots > 0 && (
<div style={{ marginTop: '8px' }}>
<Typography variant="body2" sx={{ fontWeight: 600, color: '#888' }}>
{t('Looking for your robot!')}
</Typography>
<LinearProgress
sx={{ marginTop: '4px', height: '4px', borderRadius: '2px', backgroundColor: '#e0e0e0' }}
/>
</div> </div>
)} )}
</Typography> </ListItemText>
{loadingRobots > 0 ? ( <ListItemAvatar sx={{ minWidth: 0, marginLeft: '16px' }}> {/* Adjusted minWidth and marginLeft */}
<> <RobotAvatar
<b>{t('Looking for your robot!')}</b> avatarClass="profileAvatar"
<LinearProgress /> style={{
</> width: 65,
) : ( height: 65,
<></> border: '2px solid #fcba03',
)} borderRadius: '50%',
</ListItemText> flexShrink: 0, // Prevent shrinking
}}
hashId={garage.getSlot()?.hashId ?? ''}
/>
</ListItemAvatar>
</ListItem>
<ListItemAvatar> <Divider sx={{ margin: '12px 0', backgroundColor: '#e0e0e0' }} />
<RobotAvatar </List>
avatarClass='profileAvatar'
style={{ width: 65, height: 65 }}
hashId={garage.getSlot()?.hashId ?? ''}
/>
</ListItemAvatar>
</ListItem>
<Divider /> <Typography
</List> variant="subtitle1"
sx={{ fontWeight: 600, color: '#333', marginBottom: '12px' }}
>
{t('Coordinators that know your robot:')}
</Typography>
<Typography> {federation.getCoordinators().map((coordinator: Coordinator) => {
<b>{t('Coordinators that know your robot:')}</b> const coordinatorRobot = garage.getSlot()?.getRobot(coordinator.shortAlias);
</Typography> return (
<div
{federation.getCoordinators().map((coordinator: Coordinator): React.JSX.Element => { key={coordinator.shortAlias}
const coordinatorRobot = garage.getSlot()?.getRobot(coordinator.shortAlias); style={{ marginBottom: '12px', padding: '8px', borderRadius: '4px' }}
return ( >
<div key={coordinator.shortAlias}> <RobotInfo
<RobotInfo coordinator={coordinator}
coordinator={coordinator} onClose={onClose}
onClose={onClose} disabled={coordinatorRobot?.loading}
disabled={coordinatorRobot?.loading} />
/> </div>
</div> );
); })}
})} </DialogContent>
</DialogContent> </Dialog>
</Dialog> {/* New ClaimRewardDialog */}
<ClaimRewardDialog
open={isClaimRewardDialogOpen}
onClose={handleCloseClaimRewardDialog}
t={t} // Pass translation function
/>
</>
); );
}; };