diff --git a/ackages/frontend/src/components/CelebrityProfile.jsx b/ackages/frontend/src/components/CelebrityProfile.jsx index a6a96e6..be8b67f 100644 --- a/ackages/frontend/src/components/CelebrityProfile.jsx +++ b/ackages/frontend/src/components/CelebrityProfile.jsx @@ -35,6 +35,12 @@ function CelebrityProfile() { const handleFieldSave = async (fieldName, newValue) => { // Converte stringa vuota a null per il backend const valueToSend = newValue === '' ? null : newValue; + + // Converti la stringa 'true'/'false' in un booleano per il campo specifico + if (fieldName === 'boobs_are_natural') { + valueToSend = newValue === 'true'; + } + const payload = { [fieldName]: valueToSend }; try { diff --git a/gemini-schema.json b/gemini-schema.json new file mode 100644 index 0000000..416c5a4 --- /dev/null +++ b/gemini-schema.json @@ -0,0 +1,249 @@ +{ + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Il nome principale della celebrità.", + "minLength": 1 + }, + "gender": { + "type": "string", + "enum": [ + "male", + "female", + "other" + ], + "description": "Il genere della celebrità." + }, + "birth_date": { + "type": "string", + "format": "date", + "description": "La data di nascita in formato ISO 8601 (YYYY-MM-DD)." + }, + "birth_place": { + "type": "string" + }, + "nationality": { + "type": "string" + }, + "ethnicity": { + "type": "string" + }, + "sexuality": { + "type": "string" + }, + "physical_details": { + "type": "object", + "properties": { + "hair_color": { + "type": "string" + }, + "eye_color": { + "type": "string" + }, + "height_cm": { + "type": "integer", + "minimum": 1 + }, + "weight_kg": { + "type": "integer", + "minimum": 1 + }, + "body_type": { + "type": "string" + }, + "measurements_cm": { + "type": "object", + "properties": { + "bust": { + "type": "integer", + "minimum": 1 + }, + "waist": { + "type": "integer", + "minimum": 1 + }, + "hips": { + "type": "integer", + "minimum": 1 + }, + "chest_circumference": { + "type": "integer", + "minimum": 1 + } + }, + "propertyOrdering": [ + "bust", + "waist", + "hips", + "chest_circumference" + ], + "description": "Misure del corpo in centimetri." + }, + "bra_size": { + "type": "object", + "properties": { + "band": { + "type": "integer", + "minimum": 1 + }, + "cup": { + "type": "string" + }, + "system": { + "type": "string", + "enum": [ + "US", + "UK", + "EU", + "FR", + "AU", + "IT", + "JP" + ] + } + }, + "propertyOrdering": [ + "band", + "cup", + "system" + ], + "required": [ + "band", + "cup", + "system" + ], + "description": "La taglia attuale del reggiseno." + }, + "boobs_are_natural": { + "type": "boolean" + }, + "shoe_size": { + "type": "object", + "properties": { + "size": { + "type": "number" + }, + "system": { + "type": "string", + "enum": [ + "EU", + "US", + "UK" + ] + } + }, + "propertyOrdering": [ + "size", + "system" + ], + "required": [ + "size", + "system" + ] + } + }, + "propertyOrdering": [ + "hair_color", + "eye_color", + "height_cm", + "weight_kg", + "body_type", + "measurements_cm", + "bra_size", + "boobs_are_natural", + "shoe_size" + ], + "description": "Dettagli fisici e misure della celebrità." + }, + "biography": { + "type": "string" + }, + "official_website": { + "type": "string", + "format": "uri" + }, + "aliases": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Elenco di nomi alternativi o alias." + }, + "professions": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Elenco delle professioni della celebrità." + }, + "activity_periods": { + "type": "array", + "items": { + "type": "object", + "properties": { + "start_year": { + "type": "integer", + "minimum": 1900, + "maximum": 2100 + }, + "end_year": { + "type": "integer", + "minimum": 1900, + "maximum": 2100 + }, + "notes": { + "type": "string" + } + }, + "propertyOrdering": [ + "start_year", + "end_year", + "notes" + ], + "required": [ + "start_year" + ] + }, + "description": "Periodi di attività noti della carriera." + }, + "tattoos": { + "type": "array", + "items": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "body_location": { + "type": "string" + } + }, + "propertyOrdering": [ + "description", + "body_location" + ], + "required": [ + "description" + ] + }, + "description": "Elenco dei tatuaggi conosciuti." + } + }, + "propertyOrdering": [ + "name", + "gender", + "birth_date", + "birth_place", + "nationality", + "ethnicity", + "sexuality", + "physical_details", + "biography", + "official_website", + "aliases", + "professions", + "activity_periods", + "tattoos" + ] +} \ No newline at end of file diff --git a/packages/frontend/src/components/CelebrityCreate.jsx b/packages/frontend/src/components/CelebrityCreate.jsx index 59febbe..9d0519a 100644 --- a/packages/frontend/src/components/CelebrityCreate.jsx +++ b/packages/frontend/src/components/CelebrityCreate.jsx @@ -8,9 +8,11 @@ const initialFormState = { birth_date: '', height_cm: '', weight_kg: '', + body_type: '', bust_cm: '', waist_cm: '', hips_cm: '', + chest_circumference_cm: '', bra_band_size: '', bra_cup_size: '', bra_size_system: 'US', @@ -22,6 +24,9 @@ const initialFormState = { hair_color: '', eye_color: '', biography: '', + shoe_size: '', + shoe_size_system: 'EU', + official_website: '', }; function CelebrityCreate() { @@ -84,6 +89,10 @@ function CelebrityCreate() { +
@@ -91,11 +100,23 @@ function CelebrityCreate() {
- +
+ + {formData.gender === 'male' && } +
+
+ + +
+
diff --git a/packages/frontend/src/components/CelebrityProfile.css b/packages/frontend/src/components/CelebrityProfile.css index e69de29..682ef4e 100644 --- a/packages/frontend/src/components/CelebrityProfile.css +++ b/packages/frontend/src/components/CelebrityProfile.css @@ -0,0 +1,81 @@ +/* packages/frontend/src/components/CelebrityProfile.css */ + +.profile-container { + display: flex; + gap: 2rem; + align-items: flex-start; + margin-top: 2rem; +} + +.profile-sidebar { + flex: 0 0 300px; /* Larghezza fissa per la sidebar */ + position: sticky; + top: 2rem; +} + +.profile-sidebar figure { + margin: 0; + text-align: center; +} + +.profile-sidebar img { + border-radius: var(--border-radius); + margin-bottom: 1rem; + width: 100%; + height: auto; + object-fit: cover; +} + +.profile-sidebar .editable-field-container { + text-align: center; +} + +.profile-sidebar .editable-field-container label { + display: none; /* Nasconde l'etichetta "Nome" sotto la foto */ +} +.profile-sidebar .display-value { + font-size: 1.5rem; + font-weight: bold; +} + +.profile-actions { + margin-top: 1.5rem; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0.5rem; +} + +.profile-content { + flex: 1 1 auto; /* Occupa lo spazio rimanente */ + min-width: 0; +} + +.profile-content details { + border: 1px solid var(--pico-muted-border-color); + border-radius: var(--border-radius); + margin-bottom: 1rem; + padding: 0.5rem 1rem; +} + +.profile-content summary { + cursor: pointer; + font-weight: bold; + padding: 0.5rem 0; +} + +.profile-content h3 { + margin: 0; + display: inline; + font-size: 1.2rem; +} + +.profile-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 1.5rem; + margin-top: 1rem; +} + +.error-message { + color: var(--pico-color-red-500); +} \ No newline at end of file diff --git a/packages/frontend/src/components/CelebrityProfile.jsx b/packages/frontend/src/components/CelebrityProfile.jsx index 30b7b1d..4b34c58 100644 --- a/packages/frontend/src/components/CelebrityProfile.jsx +++ b/packages/frontend/src/components/CelebrityProfile.jsx @@ -4,6 +4,7 @@ import React, { useState, useEffect } from 'react'; import { useParams, useNavigate, Link } from 'react-router-dom'; import { getCelebrityById, updateCelebrity, deleteCelebrity } from '../services/api'; import EditableField from './EditableField'; +import './CelebrityProfile.css'; // Importa il nuovo CSS per il layout del profilo function CelebrityProfile() { const { id } = useParams(); @@ -25,100 +26,116 @@ function CelebrityProfile() { .catch((err) => setError(err.message)) .finally(() => setLoading(false)); } else { - navigate('/'); + navigate('/'); } }, [id, navigate]); const handleFieldSave = async (fieldName, newValue) => { - const valueToSend = newValue === '' ? null : newValue; + let valueToSend = newValue === '' ? null : newValue; + if (fieldName === 'boobs_are_natural') { + valueToSend = newValue === 'true'; + } const payload = { [fieldName]: valueToSend }; try { - await updateCelebrity(id, payload); + const updatedCelebrity = await updateCelebrity(id, payload); + // Aggiorna lo stato locale per un feedback immediato setCelebrity((prev) => ({ ...prev, [fieldName]: newValue })); + console.log('Salvataggio riuscito:', updatedCelebrity); } catch (err) { - setError(`Errore durante il salvataggio: ${err.message}`); + console.error(`Errore durante il salvataggio del campo ${fieldName}:`, err); + // Rilancia l'errore in modo che il componente figlio possa gestirlo + throw err; } }; const handleDelete = async () => { if (window.confirm(`Sei sicuro di voler eliminare ${celebrity.name}? L'azione è irreversibile.`)) { - try { - await deleteCelebrity(id); - navigate('/'); - } catch (err) { - setError(`Errore durante l'eliminazione: ${err.message}`); - } + try { + await deleteCelebrity(id); + alert(`${celebrity.name} è stato eliminato con successo.`); + navigate('/'); + } catch (err) { + setError(`Errore durante l'eliminazione: ${err.message}`); + } } }; - + if (loading) return
Caricamento profilo...
; - if (error) return

Errore: {error}

; + if (error && !celebrity) return

Errore: {error}

; if (!celebrity) return

Nessuna celebrità trovata.

; - - const genderOptions = [ { value: 'female', label: 'Female' }, { value: 'male', label: 'Male' }, { value: 'other', label: 'Other' } ]; - const braSystemOptions = [ { value: 'US', label: 'US' }, { value: 'UK', label: 'UK' }, { value: 'EU', label: 'EU' }, { value: 'FR', label: 'FR' }, { value: 'AU', label: 'AU' }, { value: 'IT', label: 'IT' }, { value: 'JP', label: 'JP' }]; - const booleanOptions = [ { value: 'true', label: 'Sì' }, { value: 'false', label: 'No' }]; + + const genderOptions = [{ value: 'female', label: 'Female' }, { value: 'male', label: 'Male' }, { value: 'other', label: 'Other' }]; + const braSystemOptions = [{ value: 'US', label: 'US' }, { value: 'UK', label: 'UK' }, { value: 'EU', label: 'EU' }, { value: 'FR', label: 'FR' }, { value: 'AU', label: 'AU' }, { value: 'IT', label: 'IT' }, { value: 'JP', label: 'JP' }]; + const shoeSystemOptions = [{ value: 'EU', label: 'EU' }, { value: 'US', label: 'US' }, { value: 'UK', label: 'UK' }]; + const booleanOptions = [{ value: 'true', label: 'Sì' }, { value: 'false', label: 'No' }]; return ( -
-