diff --git a/attached_assets/CleanShot_2025-12-30_at_09.20.12_1767039650635.png b/attached_assets/CleanShot_2025-12-30_at_09.20.12_1767039650635.png new file mode 100644 index 0000000..d6ce07d Binary files /dev/null and b/attached_assets/CleanShot_2025-12-30_at_09.20.12_1767039650635.png differ diff --git a/attached_assets/CleanShot_2025-12-30_at_16.25.09_1767065119363.png b/attached_assets/CleanShot_2025-12-30_at_16.25.09_1767065119363.png new file mode 100644 index 0000000..0e98bc2 Binary files /dev/null and b/attached_assets/CleanShot_2025-12-30_at_16.25.09_1767065119363.png differ diff --git a/client/src/components/enhanced-ranking-card.tsx b/client/src/components/enhanced-ranking-card.tsx index 2499978..f579031 100644 --- a/client/src/components/enhanced-ranking-card.tsx +++ b/client/src/components/enhanced-ranking-card.tsx @@ -9,6 +9,7 @@ import { TrendingUp, TrendingDown, Minus, + User, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; @@ -22,6 +23,7 @@ interface EnhancedRankingCardProps { description: string; votes: number; niche?: string | null; + suggestedByUsername?: string; position?: { current: number | null; previous: number | null; @@ -332,6 +334,18 @@ export default function EnhancedRankingCard({ })} )} + + {/* Suggested by audience badge */} + {idea.suggestedByUsername && ( + + + {t("ideas.suggestedByAudience")} + + )} {/* Badge de cambio de posición */} {getTrendIcon()} diff --git a/client/src/components/idea-card.tsx b/client/src/components/idea-card.tsx index c2d00c2..154dff3 100644 --- a/client/src/components/idea-card.tsx +++ b/client/src/components/idea-card.tsx @@ -249,13 +249,15 @@ export default function IdeaCard({ )} - {/* Mostrar badge si la idea fue sugerida por otro usuario */} + {/* Mostrar badge si la idea fue sugerida - username para creador, anónimo para público */} {idea.suggestedByUsername && (
- {t("ideas.suggestedBy")}:{" "} - {idea.suggestedByUsername} + {isCreator + ? `${t("ideas.suggestedBy")}: ${idea.suggestedByUsername}` + : t("ideas.suggestedByAudience") + }
)} diff --git a/client/src/components/idea-form.tsx b/client/src/components/idea-form.tsx index 0a9d471..fe059fc 100644 --- a/client/src/components/idea-form.tsx +++ b/client/src/components/idea-form.tsx @@ -252,7 +252,8 @@ export default function IdeaForm({ isOpen, idea, onClose }: IdeaFormProps) { name="title" render={({ field }) => ( - + + 💡 {t("ideaForm.title", "Title")} @@ -274,7 +275,8 @@ export default function IdeaForm({ isOpen, idea, onClose }: IdeaFormProps) { name="description" render={({ field }) => ( - + + 📝 {t("ideaForm.description", "Description")} @@ -302,7 +304,8 @@ export default function IdeaForm({ isOpen, idea, onClose }: IdeaFormProps) { name="niche" render={({ field }) => ( - + + 🎯 {t("ideaForm.niche", "Niche")} @@ -403,7 +406,7 @@ export default function IdeaForm({ isOpen, idea, onClose }: IdeaFormProps) { disabled={ createMutation.isPending || updateMutation.isPending } - className="flex-1 sm:flex-none h-12 rounded-md bg-gradient-to-r from-primary to-primary/90 hover:from-primary/90 hover:to-primary text-white font-semibold shadow-lg hover:shadow-xl transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" + className="flex-1 sm:flex-none h-12 rounded-md border-2 border-primary/30 bg-primary/10 hover:bg-primary/20 text-primary font-semibold transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" > {createMutation.isPending || updateMutation.isPending ? ( diff --git a/client/src/components/idea-list-view.tsx b/client/src/components/idea-list-view.tsx index 9972c1c..975b0e0 100644 --- a/client/src/components/idea-list-view.tsx +++ b/client/src/components/idea-list-view.tsx @@ -194,6 +194,21 @@ export default function IdeaListView({ {t("ideas.analyzed", "Analizado")} )} + + {/* Suggested by badge - show username for creator, anonymous for public */} + {idea.suggestedByUsername && ( + + + {isCreator + ? `${t("ideas.suggestedBy")}: ${idea.suggestedByUsername}` + : t("ideas.suggestedByAudience") + } + + )} {/* Title */} diff --git a/client/src/components/ideas-list.tsx b/client/src/components/ideas-list.tsx index 4ca758a..4ca1e52 100644 --- a/client/src/components/ideas-list.tsx +++ b/client/src/components/ideas-list.tsx @@ -1,6 +1,7 @@ import { motion } from "framer-motion"; -import { TrendingUp, Loader2 } from "lucide-react"; +import { TrendingUp, Loader2, User } from "lucide-react"; import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; import { IdeaResponse } from "@shared/schema"; import { useTranslation } from "react-i18next"; import { cn } from "@/lib/utils"; @@ -88,6 +89,16 @@ export function IdeasList({

{idea.description}

+ {idea.suggestedByUsername && ( + + + {t("ideas.suggestedByAudience")} + + )}
diff --git a/client/src/components/ideas-tab-view.tsx b/client/src/components/ideas-tab-view.tsx index 0608c5d..6fb7b9c 100644 --- a/client/src/components/ideas-tab-view.tsx +++ b/client/src/components/ideas-tab-view.tsx @@ -563,15 +563,15 @@ export function IdeasTabView({ mode = "published", onOpenTemplate }: IdeasTabVie key={idea.id} className="group bg-white/80 dark:bg-gray-900/80 backdrop-blur-sm border border-gray-200/50 dark:border-gray-700/50 rounded-2xl p-4 hover:bg-white/90 dark:hover:bg-gray-900/90 hover:shadow-lg transition-all duration-300 hover:border-gray-300/60 dark:hover:border-gray-600/60" > -
- {/* Position */} -
-
+
+ {/* Position - horizontal on mobile, vertical on desktop */} +
+
#{index + 1}
{t("ideas.pending", "Pendiente")} @@ -579,9 +579,9 @@ export function IdeasTabView({ mode = "published", onOpenTemplate }: IdeasTabVie {/* Content */}
-
+
-

+

{idea.title}

{idea.description && ( @@ -615,7 +615,8 @@ export function IdeasTabView({ mode = "published", onOpenTemplate }: IdeasTabVie ) : ( <> - {t("ideas.reject", "Rechazar")} + {t("ideas.reject", "Rechazar")} + {t("ideas.reject", "Rechazar")} )} @@ -631,7 +632,8 @@ export function IdeasTabView({ mode = "published", onOpenTemplate }: IdeasTabVie ) : ( <> - {t("ideas.approve", "Aprobar")} + {t("ideas.approve", "Aprobar")} + {t("ideas.approve", "Aprobar")} )} diff --git a/client/src/components/top3-cards.tsx b/client/src/components/top3-cards.tsx index 81cb049..6628e4f 100644 --- a/client/src/components/top3-cards.tsx +++ b/client/src/components/top3-cards.tsx @@ -1,6 +1,7 @@ import { motion } from "framer-motion"; -import { Trophy, TrendingUp } from "lucide-react"; +import { Trophy, TrendingUp, User } from "lucide-react"; import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; import { IdeaResponse } from "@shared/schema"; import { useTranslation } from "react-i18next"; import { cn } from "@/lib/utils"; @@ -121,10 +122,15 @@ export function Top3Cards({
- {idea.suggestedBy && ( - - {t("ideas.by", "Por")} {idea.suggestedBy} - + {idea.suggestedByUsername && ( + + + {t("ideas.suggestedByAudience")} + )}
{/* Vote Section */} diff --git a/client/src/components/video-template-modal.tsx b/client/src/components/video-template-modal.tsx index 651ca17..8423a0e 100644 --- a/client/src/components/video-template-modal.tsx +++ b/client/src/components/video-template-modal.tsx @@ -57,6 +57,7 @@ interface Section { labelKey: string; placeholderKey: string; icon: typeof Eye; + emoji?: string; } export default function VideoTemplateModal({ @@ -70,15 +71,15 @@ export default function VideoTemplateModal({ const { user } = useAuth(); const isPremium = user ? hasActivePremiumAccess(user) : false; - // Define sections with translation keys + // Define sections with translation keys and emojis const sections: Section[] = [ - { key: "hook", labelKey: "videoScript.sections.hook", placeholderKey: "videoScript.sections.hookPlaceholder", icon: Eye }, - { key: "teaser", labelKey: "videoScript.sections.teaser", placeholderKey: "videoScript.sections.teaserPlaceholder", icon: Eye }, - { key: "valorAudiencia", labelKey: "videoScript.sections.valueForAudience", placeholderKey: "videoScript.sections.valueForAudiencePlaceholder", icon: Eye }, - { key: "pointsToCover", labelKey: "videoScript.sections.pointsToCover", placeholderKey: "videoScript.sections.pointsToCoverPlaceholder", icon: Eye }, - { key: "visualsNeeded", labelKey: "videoScript.sections.visualsNeeded", placeholderKey: "videoScript.sections.visualsNeededPlaceholder", icon: Eye }, - { key: "bonus", labelKey: "videoScript.sections.bonus", placeholderKey: "videoScript.sections.bonusPlaceholder", icon: Eye }, - { key: "outro", labelKey: "videoScript.sections.outro", placeholderKey: "videoScript.sections.outroPlaceholder", icon: Eye }, + { key: "hook", labelKey: "videoScript.sections.hook", placeholderKey: "videoScript.sections.hookPlaceholder", icon: Eye, emoji: "🎣" }, + { key: "teaser", labelKey: "videoScript.sections.teaser", placeholderKey: "videoScript.sections.teaserPlaceholder", icon: Eye, emoji: "✨" }, + { key: "valorAudiencia", labelKey: "videoScript.sections.valueForAudience", placeholderKey: "videoScript.sections.valueForAudiencePlaceholder", icon: Eye, emoji: "💎" }, + { key: "pointsToCover", labelKey: "videoScript.sections.pointsToCover", placeholderKey: "videoScript.sections.pointsToCoverPlaceholder", icon: Eye, emoji: "📋" }, + { key: "visualsNeeded", labelKey: "videoScript.sections.visualsNeeded", placeholderKey: "videoScript.sections.visualsNeededPlaceholder", icon: Eye, emoji: "🎬" }, + { key: "bonus", labelKey: "videoScript.sections.bonus", placeholderKey: "videoScript.sections.bonusPlaceholder", icon: Eye, emoji: "🎁" }, + { key: "outro", labelKey: "videoScript.sections.outro", placeholderKey: "videoScript.sections.outroPlaceholder", icon: Eye, emoji: "👋" }, ]; // Text fields @@ -288,17 +289,17 @@ ${outro.length > 0 ? `## OUTRO / CTA\n${formatItems(outro)}\n` : ''} @@ -345,13 +346,14 @@ ${outro.length > 0 ? `## OUTRO / CTA\n${formatItems(outro)}\n` : ''} onChange={(e) => setNewInputs({ ...newInputs, [section.key]: e.target.value })} placeholder={t(section.placeholderKey)} onKeyPress={(e) => e.key === "Enter" && handleAddItem(section.key)} - className="flex-1" + className="flex-1 border-2 border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 focus:border-primary/50 text-gray-900 dark:text-white" data-testid={`input-new-${section.key}`} />