diff --git a/firebase-blueprint.json b/firebase-blueprint.json index 71105ba..8d04601 100644 --- a/firebase-blueprint.json +++ b/firebase-blueprint.json @@ -37,6 +37,22 @@ "result": { "type": "string" } }, "required": ["userId", "pair", "decision", "timestamp"] + }, + "Testimonial": { + "title": "User Testimonial", + "description": "Public review left by a user.", + "type": "object", + "properties": { + "userId": { "type": "string" }, + "userName": { "type": "string" }, + "text": { "type": "string" }, + "timestamp": { "type": "integer" }, + "imageUrls": { + "type": "array", + "items": { "type": "string" } + } + }, + "required": ["userId", "userName", "text", "timestamp"] } }, "firestore": { @@ -47,6 +63,10 @@ "signals/{signalId}": { "schema": "Signal", "description": "Generated signals." + }, + "testimonials/{testimonialId}": { + "schema": "Testimonial", + "description": "Public user testimonials." } } } diff --git a/firestore.rules b/firestore.rules index 3541ebc..d779970 100644 --- a/firestore.rules +++ b/firestore.rules @@ -93,5 +93,23 @@ service cloud.firestore { allow update, delete: if isDbAdmin(); } + + // --- Testimonials Collection --- + match /testimonials/{testimonialId} { + allow read: if true; + + function isValidTestimonial(data) { + return data.keys().hasAll(['userId', 'userName', 'text', 'timestamp', 'imageUrls']) + && (data.userId == request.auth.uid || isDbAdmin()) + && data.userName is string && data.userName.size() <= 100 + && data.text is string && data.text.size() <= 500 + && data.timestamp is int + && data.imageUrls is list && data.imageUrls.size() <= 10 + && (data.imageUrls.size() == 0 || data.imageUrls[0] is string); + } + + allow create: if isSignedIn() && isValidTestimonial(incoming()); + allow update, delete: if isDbAdmin(); + } } } diff --git a/src/components/AddTestimonialForm.tsx b/src/components/AddTestimonialForm.tsx new file mode 100644 index 0000000..d8dd4a6 --- /dev/null +++ b/src/components/AddTestimonialForm.tsx @@ -0,0 +1,58 @@ +import React, { useState } from 'react'; +import { collection, addDoc } from 'firebase/firestore'; +import { db, auth } from '../lib/firebase'; +import { ImageUploader } from './ImageUploader'; + +export const AddTestimonialForm: React.FC = () => { + const [text, setText] = useState(''); + const [imageUrls, setImageUrls] = useState([]); + const [submitting, setSubmitting] = useState(false); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + if (!auth.currentUser || !text.trim()) return; + + setSubmitting(true); + try { + await addDoc(collection(db, 'testimonials'), { + userId: auth.currentUser.uid, + userName: auth.currentUser.email || 'Usuário', + text: text, + timestamp: Date.now(), + imageUrls: imageUrls + }); + setText(''); + setImageUrls([]); + alert('Resultado enviado com sucesso!'); + } catch (error) { + console.error(error); + alert('Erro ao enviar resultado.'); + } finally { + setSubmitting(false); + } + }; + + if (!auth.currentUser) return null; + + return ( +
+

Deixe o seu resultado

+