add: shop capes and refactor cape card

This commit is contained in:
2025-07-19 01:36:33 +05:00
parent 26f601635b
commit 56da7c7543
4 changed files with 315 additions and 62 deletions

View File

@ -20,13 +20,10 @@ import {
MenuItem,
Alert,
CircularProgress,
Card,
CardContent,
CardMedia,
Tooltip,
CardActions,
} from '@mui/material';
import CapeCard from '../components/CapeCard';
export default function Profile() {
const fileInputRef = useRef<HTMLInputElement>(null);
const [walkingSpeed, setWalkingSpeed] = useState<number>(0.5);
@ -317,63 +314,24 @@ export default function Profile() {
}}
>
<Typography>Ваши плащи</Typography>
<Box sx={{ display: 'flex', flexDirection: 'row', gap: 2 }}>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
gap: 2,
flexWrap: 'wrap',
}}
>
{capes.map((cape) => (
<Tooltip arrow title={cape.cape_description}>
<Card
key={cape.cape_id}
sx={{
bgcolor: 'rgba(255, 255, 255, 0.05)',
width: 200, // фиксированная ширина карточки
overflow: 'hidden',
}}
>
<CardMedia
component="img"
image={cape.image_url}
alt={cape.cape_name}
sx={{
display: 'block',
width: '100%',
transform:
'scale(2.9) translateX(66px) translateY(32px)',
imageRendering: 'pixelated',
}}
/>
<CardContent
sx={{ bgcolor: 'rgba(255, 255, 255, 0.05)', pt: '9vh' }}
>
<Typography sx={{ color: 'white' }}>
{cape.cape_name}
</Typography>
</CardContent>
{cape.is_active ? (
<CardActions
sx={{ display: 'flex', justifyContent: 'center' }}
>
<Button
variant="contained"
sx={{ bgcolor: 'red' }}
onClick={() => handleDeactivateCape(cape.cape_id)}
>
Снять
</Button>
</CardActions>
) : (
<CardActions
sx={{ display: 'flex', justifyContent: 'center' }}
>
<Button
variant="contained"
sx={{ bgcolor: 'green' }}
onClick={() => handleActivateCape(cape.cape_id)}
>
Надеть
</Button>
</CardActions>
)}
</Card>
</Tooltip>
<CapeCard
key={cape.cape_id}
cape={cape}
mode="profile"
onAction={
cape.is_active ? handleDeactivateCape : handleActivateCape
}
actionDisabled={loading}
/>
))}
</Box>
</Box>

View File

@ -1,3 +1,127 @@
import { Box } from '@mui/material';
import { Typography } from '@mui/material';
import CapeCard from '../components/CapeCard';
import {
Cape,
fetchCapes,
fetchCapesStore,
purchaseCape,
StoreCape,
} from '../api';
import { useEffect, useState } from 'react';
export default function Shop() {
return <div>Shop</div>;
const [storeCapes, setStoreCapes] = useState<StoreCape[]>([]);
const [userCapes, setUserCapes] = useState<Cape[]>([]);
const [username, setUsername] = useState<string>('');
const [uuid, setUuid] = useState<string>('');
const [loading, setLoading] = useState<boolean>(false);
// Функция для загрузки плащей из магазина
const loadStoreCapes = async () => {
try {
const capes = await fetchCapesStore();
setStoreCapes(capes);
} catch (error) {
console.error('Ошибка при получении плащей магазина:', error);
setStoreCapes([]);
}
};
// Функция для загрузки плащей пользователя
const loadUserCapes = async (username: string) => {
try {
const userCapes = await fetchCapes(username);
setUserCapes(userCapes);
} catch (error) {
console.error('Ошибка при получении плащей пользователя:', error);
setUserCapes([]);
}
};
const handlePurchaseCape = async (cape_id: string) => {
try {
await purchaseCape(username, cape_id);
await loadUserCapes(username);
} catch (error) {
console.error('Ошибка при покупке плаща:', error);
}
};
// Загружаем данные при монтировании
useEffect(() => {
const savedConfig = localStorage.getItem('launcher_config');
if (savedConfig) {
const config = JSON.parse(savedConfig);
if (config.uuid && config.username) {
setUsername(config.username);
setUuid(config.uuid);
setLoading(true);
// Загружаем оба списка плащей
Promise.all([loadStoreCapes(), loadUserCapes(config.username)]).finally(
() => {
setLoading(false);
},
);
}
}
}, []);
// Фильтруем плащи, которые уже куплены пользователем
const availableCapes = storeCapes.filter(
(storeCape) =>
!userCapes.some((userCape) => userCape.cape_id === storeCape.id),
);
return (
<Box
sx={{
display: 'flex',
flexDirection: 'column',
gap: '2vw',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Typography variant="h4">Shop</Typography>
{loading ? (
<Typography>Загрузка...</Typography>
) : (
<Box
sx={{
display: 'flex',
flexDirection: 'column',
gap: '2vw',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Typography variant="h6">Доступные плащи</Typography>
{availableCapes.length > 0 ? (
<Box
sx={{
display: 'flex',
flexDirection: 'row',
gap: '2vw',
flexWrap: 'wrap',
}}
>
{availableCapes.map((cape) => (
<CapeCard
key={cape.id}
cape={cape}
mode="shop"
onAction={handlePurchaseCape}
/>
))}
</Box>
) : (
<Typography>У вас уже есть все доступные плащи!</Typography>
)}
</Box>
)}
</Box>
);
}