This commit is contained in:
Marces Zastrow
2025-01-10 10:16:24 +01:00
parent 615db54e24
commit b56b73754c
3 changed files with 429 additions and 5 deletions
+419
View File
@@ -0,0 +1,419 @@
import React, { useState, useContext } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { UserContext } from '../context/UserContext';
import axios from 'axios';
import {
Box,
TextField,
Button,
Typography,
Select,
MenuItem,
FormControl,
InputLabel,
Grid2
} from '@mui/material';
const CreateCharacter = () => {
const navigate = useNavigate();
const location = useLocation();
const { userId } = useContext(UserContext);
const gameId = new URLSearchParams(location.search).get('gameId');
const [formData, setFormData] = useState({
charName: '',
race: '',
sex: '',
age: '',
job: '',
description: '',
maxHealth: 100,
maxMana: 100,
strength: 10,
dexterity: 10,
agility: 10,
endurance: 10
});
const [selectedImage, setSelectedImage] = useState(null);
const [imagePreview, setImagePreview] = useState(null);
const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value
});
};
const handleImageChange = (e) => {
const file = e.target.files[0];
if (file) {
setSelectedImage(file);
setImagePreview(URL.createObjectURL(file));
}
};
const handleSubmit = async (e) => {
e.preventDefault();
const formDataToSend = new FormData();
// Append all form data
Object.keys(formData).forEach(key => {
formDataToSend.append(key, formData[key]);
});
// Append image if exists
if (selectedImage) {
formDataToSend.append('image', selectedImage);
}
try {
await axios.post('http://localhost:5000/games/character/create',
formDataToSend,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}
);
navigate(`/games/${gameId}`);
} catch (error) {
console.error('Error creating character:', error);
}
};
return (
<Box sx={{
p: 3,
background: 'rgba(30, 30, 47, 0.9)',
borderRadius: '8px',
marginTop: '40px',
maxWidth: '800px',
margin: '40px auto'
}}>
<Typography variant="h4" sx={{ mb: 4, color: '#fff', textAlign: 'center' }}>
Create New Character
</Typography>
<form onSubmit={handleSubmit}>
<Grid2 container spacing={2}>
{/* Basic Info */}
<Grid2 item xs={12}>
<TextField
fullWidth
label="Character Name"
name="charName"
value={formData.charName}
onChange={handleChange}
required
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: '#444',
},
'&:hover fieldset': {
borderColor: '#764ACB',
},
'&.Mui-focused fieldset': {
borderColor: '#764ACB',
},
},
'& .MuiInputLabel-root': {
color: '#fff',
},
'& .MuiInputBase-input': {
color: '#fff',
}
}}
/>
</Grid2>
{/* Image Upload */}
<Grid2 item xs={12}>
<input
accept="image/*"
type="file"
id="image-upload"
style={{ display: 'none' }}
onChange={handleImageChange}
/>
<label htmlFor="image-upload">
<Button
variant="contained"
component="span"
sx={{
backgroundColor: '#764ACB',
'&:hover': { backgroundColor: '#9865f7' },
mb: 2
}}
>
Upload Character Image
</Button>
</label>
{imagePreview && (
<Box sx={{ mt: 2, mb: 2 }}>
<img
src={imagePreview}
alt="Preview"
style={{
maxWidth: '200px',
borderRadius: '4px',
border: '1px solid #444'
}}
/>
</Box>
)}
</Grid2>
{/* Character Details */}
<Grid2 container item spacing={2}>
<Grid2 item xs={12} md={6}>
<FormControl fullWidth sx={{ mb: 2 }}>
<InputLabel sx={{ color: '#fff' }}>Race</InputLabel>
<Select
name="race"
value={formData.race}
onChange={handleChange}
required
sx={{
color: '#fff',
'& .MuiOutlinedInput-notchedOutline': {
borderColor: '#444',
},
'&:hover .MuiOutlinedInput-notchedOutline': {
borderColor: '#764ACB',
},
'&.Mui-focused .MuiOutlinedInput-notchedOutline': {
borderColor: '#764ACB',
},
'& .MuiSelect-icon': {
color: '#fff',
}
}}
>
<MenuItem value="Human">Human</MenuItem>
<MenuItem value="Elf">Elf</MenuItem>
<MenuItem value="Dwarf">Dwarf</MenuItem>
<MenuItem value="Orc">Orc</MenuItem>
</Select>
</FormControl>
</Grid2>
<Grid2 item xs={12} md={6}>
<FormControl fullWidth>
<InputLabel sx={{ color: '#fff' }}>Sex</InputLabel>
<Select
name="sex"
value={formData.sex}
onChange={handleChange}
required
sx={{ color: '#fff', '& fieldset': { borderColor: '#444' } }}
>
<MenuItem value="Male">Male</MenuItem>
<MenuItem value="Female">Female</MenuItem>
<MenuItem value="Other">Other</MenuItem>
</Select>
</FormControl>
</Grid2>
<Grid2 item xs={12} md={6}>
<TextField
fullWidth
label="Age"
name="age"
type="number"
value={formData.age}
onChange={handleChange}
required
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: '#444' },
'&:hover fieldset': { borderColor: '#764ACB' },
},
'& .MuiInputLabel-root': { color: '#fff' },
'& .MuiInputBase-input': { color: '#fff' }
}}
/>
</Grid2>
<Grid2 item xs={12} md={6}>
<TextField
fullWidth
label="Job/Class"
name="job"
value={formData.job}
onChange={handleChange}
required
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: '#444' },
'&:hover fieldset': { borderColor: '#764ACB' },
},
'& .MuiInputLabel-root': { color: '#fff' },
'& .MuiInputBase-input': { color: '#fff' }
}}
/>
</Grid2>
{/* Stats */}
<Grid2 item xs={12} md={6}>
<TextField
fullWidth
label="Max Health"
name="maxHealth"
type="number"
value={formData.maxHealth}
onChange={handleChange}
required
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: '#444' },
'&:hover fieldset': { borderColor: '#764ACB' },
},
'& .MuiInputLabel-root': { color: '#fff' },
'& .MuiInputBase-input': { color: '#fff' }
}}
/>
</Grid2>
<Grid2 item xs={12} md={6}>
<TextField
fullWidth
label="Max Mana"
name="maxMana"
type="number"
value={formData.maxMana}
onChange={handleChange}
required
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: '#444' },
'&:hover fieldset': { borderColor: '#764ACB' },
},
'& .MuiInputLabel-root': { color: '#fff' },
'& .MuiInputBase-input': { color: '#fff' }
}}
/>
</Grid2>
<Grid2 item xs={12} md={6}>
<TextField
fullWidth
label="Strength"
name="strength"
type="number"
value={formData.strength}
onChange={handleChange}
required
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: '#444' },
'&:hover fieldset': { borderColor: '#764ACB' },
},
'& .MuiInputLabel-root': { color: '#fff' },
'& .MuiInputBase-input': { color: '#fff' }
}}
/>
</Grid2>
<Grid2 item xs={12} md={6}>
<TextField
fullWidth
label="Dexterity"
name="dexterity"
type="number"
value={formData.dexterity}
onChange={handleChange}
required
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: '#444' },
'&:hover fieldset': { borderColor: '#764ACB' },
},
'& .MuiInputLabel-root': { color: '#fff' },
'& .MuiInputBase-input': { color: '#fff' }
}}
/>
</Grid2>
<Grid2 item xs={12} md={6}>
<TextField
fullWidth
label="Agility"
name="agility"
type="number"
value={formData.agility}
onChange={handleChange}
required
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: '#444' },
'&:hover fieldset': { borderColor: '#764ACB' },
},
'& .MuiInputLabel-root': { color: '#fff' },
'& .MuiInputBase-input': { color: '#fff' }
}}
/>
</Grid2>
<Grid2 item xs={12} md={6}>
<TextField
fullWidth
label="Endurance"
name="endurance"
type="number"
value={formData.endurance}
onChange={handleChange}
required
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: '#444' },
'&:hover fieldset': { borderColor: '#764ACB' },
},
'& .MuiInputLabel-root': { color: '#fff' },
'& .MuiInputBase-input': { color: '#fff' }
}}
/>
</Grid2>
{/* Description */}
<Grid2 item xs={12}>
<TextField
fullWidth
label="Description"
name="description"
multiline
rows={4}
value={formData.description}
onChange={handleChange}
sx={{
'& .MuiOutlinedInput-root': {
'& fieldset': { borderColor: '#444' },
'&:hover fieldset': { borderColor: '#764ACB' },
},
'& .MuiInputLabel-root': { color: '#fff' },
'& .MuiInputBase-input': { color: '#fff' }
}}
/>
</Grid2>
</Grid2>
</Grid2>
<Button
type="submit"
variant="contained"
fullWidth
sx={{
backgroundColor: '#764ACB',
'&:hover': { backgroundColor: '#9865f7' },
mt: 3
}}
>
Create Character
</Button>
</form>
</Box>
);
};
export default CreateCharacter;
+1 -1
View File
@@ -100,7 +100,7 @@ const GamesPage = () => {
}
}}
component={Link}
to="/create-character"
to={`/create-character?gameId=${gameId}`}
>
Create New Character
</Button>