feedback do utilizador

This commit is contained in:
2026-04-22 10:35:29 +01:00
parent 2cf8184feb
commit 92857c8d3a

View File

@@ -165,12 +165,12 @@ export default function App() {
const locName = userProfile?.location || 'Lisboa, Portugal';
const geoRes = await fetch(`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(locName)}&count=1&language=pt&format=json`);
const geoData = await geoRes.json();
if (geoData.results && geoData.results.length > 0) {
const { latitude, longitude, name, country } = geoData.results[0];
const weatherRes = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current_weather=true&daily=temperature_2m_max,temperature_2m_min&timezone=auto`);
const weatherRaw = await weatherRes.json();
if (weatherRaw.current_weather && weatherRaw.daily) {
setWeatherData({
name: `${name}, ${country || ''}`.replace(/,\s*$/, ''),
@@ -210,7 +210,7 @@ export default function App() {
}
});
if (totalWithColor === 0) return [];
return Object.entries(colorCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, 3)
@@ -275,7 +275,7 @@ export default function App() {
try {
// Guardamos o id se for edição antes de apagar o estado
const currentEditId = editingItem ? editingItem.id : null;
// Navegação instantânea (Optimistic UI Update)
setEditingItem(null);
setImageUrlDraft('');
@@ -426,7 +426,7 @@ export default function App() {
e.preventDefault();
setSavingProfile(true);
const fd = new FormData(e.target);
try {
const profileDoc = doc(db, 'artifacts', appId, 'users', user.uid, 'profile', 'data');
const dobDay = fd.get('dobDay');
@@ -907,15 +907,15 @@ export default function App() {
<div className="flex gap-2">
<select name="dobDay" defaultValue={userProfile?.dob?.split('-')[2] || ''} className={`flex-1 p-4 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500 font-bold ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}>
<option value="">DD</option>
{Array.from({length: 31}, (_, i) => String(i+1).padStart(2,'0')).map(d => <option key={d} value={d}>{d}</option>)}
{Array.from({ length: 31 }, (_, i) => String(i + 1).padStart(2, '0')).map(d => <option key={d} value={d}>{d}</option>)}
</select>
<select name="dobMonth" defaultValue={userProfile?.dob?.split('-')[1] || ''} className={`flex-1 p-4 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500 font-bold ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}>
<option value="">MM</option>
{Array.from({length: 12}, (_, i) => String(i+1).padStart(2,'0')).map(m => <option key={m} value={m}>{m}</option>)}
{Array.from({ length: 12 }, (_, i) => String(i + 1).padStart(2, '0')).map(m => <option key={m} value={m}>{m}</option>)}
</select>
<select name="dobYear" defaultValue={userProfile?.dob?.split('-')[0] || ''} className={`flex-[1.5] p-4 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500 font-bold ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}>
<option value="">YYYY</option>
{Array.from({length: 100}, (_, i) => new Date().getFullYear() - i).map(y => <option key={y} value={y}>{y}</option>)}
{Array.from({ length: 100 }, (_, i) => new Date().getFullYear() - i).map(y => <option key={y} value={y}>{y}</option>)}
</select>
</div>
</div>
@@ -994,11 +994,11 @@ export default function App() {
<div>
<p className="font-bold text-inherit">{t('appLanguage')}</p>
<p className="text-[10px] uppercase tracking-widest opacity-50 text-inherit">
{language === 'PT' ? '🇵🇹 ' + t('portuguese') :
language === 'EN' ? '🇬🇧 ' + t('english') :
language === 'ES' ? '🇪🇸 ' + t('spanish') :
language === 'FR' ? '🇫🇷 ' + t('french') :
language === 'DE' ? '🇩🇪 ' + t('german') : language}
{language === 'PT' ? '🇵🇹 ' + t('portuguese') :
language === 'EN' ? '🇬🇧 ' + t('english') :
language === 'ES' ? '🇪🇸 ' + t('spanish') :
language === 'FR' ? '🇫🇷 ' + t('french') :
language === 'DE' ? '🇩🇪 ' + t('german') : language}
</p>
</div>
<button onClick={() => setShowLangModal(true)} className="px-5 py-2 font-black text-[10px] uppercase tracking-widest bg-primary-50 text-primary-600 rounded-xl hover:bg-primary-100 transition-colors dark:bg-primary-900/40 dark:text-primary-400">
@@ -1008,6 +1008,35 @@ export default function App() {
</div>
</Card>
<Card className="p-8" darkMode={darkMode}>
<h3 className="text-xl font-black mb-6 flex items-center gap-3 text-inherit"><Bell className="text-primary-600" /> {t('feedbackTitle') || 'Suporte e Feedback'}</h3>
<p className="opacity-60 text-sm font-medium mb-6">{t('feedbackDesc') || 'Tem alguma ideia, sugestão ou encontrou algum problema? Envie uma mensagem diretamente para nós!'}</p>
<form onSubmit={(e) => {
e.preventDefault();
const fd = new FormData(e.target);
const type = fd.get('type');
const msg = fd.get('message');
// Substitua pelo seu email real
const email = "faiker027@gmail.com";
window.location.href = `mailto:${email}?subject=${encodeURIComponent(`MyCloset Feedback: ${type}`)}&body=${encodeURIComponent(msg)}`;
e.target.reset();
}} className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<label className="flex items-center gap-3 p-4 rounded-xl border border-gray-100 dark:border-gray-800 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
<input type="radio" name="type" value="Ideia/Sugestão" defaultChecked className="text-primary-600 focus:ring-primary-500" />
<span className="font-bold text-sm text-inherit">Ideia / Sugestão</span>
</label>
<label className="flex items-center gap-3 p-4 rounded-xl border border-gray-100 dark:border-gray-800 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
<input type="radio" name="type" value="Bug/Erro" className="text-primary-600 focus:ring-primary-500" />
<span className="font-bold text-sm text-inherit">Bug / Erro</span>
</label>
</div>
<textarea name="message" required placeholder="Escreva aqui a sua mensagem..." rows={4} className={`w-full p-4 rounded-xl border-none outline-none focus:ring-2 focus:ring-primary-500 font-bold resize-none ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}></textarea>
<button type="submit" className="w-full py-4 bg-primary-600 text-white rounded-xl font-black uppercase text-[10px] tracking-widest shadow-xl shadow-primary-600/30 hover:scale-[1.01] transition-all">
Enviar Mensagem
</button>
</form>
</Card>
</div>
@@ -1056,7 +1085,7 @@ export default function App() {
<h3 className="text-2xl font-black text-inherit flex items-center gap-3"><Filter size={24} className="text-primary-600" /> {t('advancedFilters')}</h3>
<button onClick={() => setShowClosetFilters(false)} className="p-2 bg-gray-100 dark:bg-gray-800 rounded-full hover:scale-110 transition-all text-inherit"><X size={20} /></button>
</div>
<div className="flex-1 overflow-y-auto space-y-8 pr-2 custom-scrollbar">
<div className="space-y-4">
<label className="text-[10px] font-black uppercase opacity-40 tracking-widest ml-1 text-inherit">{t('closet')}</label>
@@ -1075,7 +1104,7 @@ export default function App() {
<div className="space-y-4">
<label className="text-[10px] font-black uppercase opacity-40 tracking-widest ml-1 text-inherit">{t('filterByColor')}</label>
<select
<select
value={colorFilter}
onChange={(e) => setColorFilter(e.target.value)}
className={`w-full p-4 rounded-2xl border-none outline-none focus:ring-2 focus:ring-primary-500 font-bold ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-50'}`}