From 7880ce8ddaaf4cb7e878b80705120cde3102961e Mon Sep 17 00:00:00 2001 From: Lucas Santana Date: Thu, 23 Jan 2025 13:28:13 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20Adicionando=20transforma=C3=A7=C3=A3o?= =?UTF-8?q?=20de=20texto=20para=20mai=C3=BAsculo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ui/adaptive-text.tsx | 89 ++++++++++++++++++++++++++ src/components/ui/text-case-toggle.tsx | 40 ++++++++++++ src/hooks/useUppercasePreference.ts | 74 +++++++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 src/components/ui/adaptive-text.tsx create mode 100644 src/components/ui/text-case-toggle.tsx create mode 100644 src/hooks/useUppercasePreference.ts diff --git a/src/components/ui/adaptive-text.tsx b/src/components/ui/adaptive-text.tsx new file mode 100644 index 0000000..4fbb934 --- /dev/null +++ b/src/components/ui/adaptive-text.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { cn } from '../../lib/utils'; + +interface AdaptiveTextProps extends React.HTMLAttributes { + text: string; + isUpperCase: boolean; + as?: keyof JSX.IntrinsicElements; + preserveWhitespace?: boolean; +} + +export const AdaptiveText = React.memo(({ + text, + isUpperCase, + as: Component = 'span', + preserveWhitespace = false, + className, + ...props +}: AdaptiveTextProps) => { + // Transformar o texto mantendo espaços em branco se necessário + const transformedText = React.useMemo(() => { + const transformed = isUpperCase ? text.toUpperCase() : text; + return preserveWhitespace ? transformed : transformed.trim(); + }, [text, isUpperCase, preserveWhitespace]); + + return React.createElement( + Component, + { + className: cn( + 'transition-colors duration-200', + className + ), + ...props + }, + transformedText + ); +}); + +AdaptiveText.displayName = 'AdaptiveText'; + +// Variantes específicas para diferentes contextos +export const AdaptiveTitle = ({ + className, + ...props +}: AdaptiveTextProps) => ( + +); + +export const AdaptiveParagraph = ({ + className, + ...props +}: AdaptiveTextProps) => ( + +); + +export const AdaptiveLabel = ({ + className, + ...props +}: AdaptiveTextProps) => ( + +); + +// Hook para memoização de textos longos +export function useAdaptiveText(text: string, isUpperCase: boolean) { + return React.useMemo( + () => isUpperCase ? text.toUpperCase() : text, + [text, isUpperCase] + ); +} \ No newline at end of file diff --git a/src/components/ui/text-case-toggle.tsx b/src/components/ui/text-case-toggle.tsx new file mode 100644 index 0000000..20ce768 --- /dev/null +++ b/src/components/ui/text-case-toggle.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { Loader2, Type } from 'lucide-react'; +import { cn } from '../../lib/utils'; + +interface TextCaseToggleProps { + isUpperCase: boolean; + onToggle: () => void; + isLoading?: boolean; + className?: string; +} + +export function TextCaseToggle({ + isUpperCase, + onToggle, + isLoading = false, + className +}: TextCaseToggleProps) { + return ( + + ); +} \ No newline at end of file diff --git a/src/hooks/useUppercasePreference.ts b/src/hooks/useUppercasePreference.ts new file mode 100644 index 0000000..05bd5c3 --- /dev/null +++ b/src/hooks/useUppercasePreference.ts @@ -0,0 +1,74 @@ +import { useState, useEffect } from 'react'; +import { supabase } from '../lib/supabase'; + +interface UseUppercasePreferenceReturn { + isUpperCase: boolean; + toggleUppercase: () => Promise; + isLoading: boolean; + error: string | null; +} + +export function useUppercasePreference(studentId?: string): UseUppercasePreferenceReturn { + const [isUpperCase, setIsUpperCase] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const loadPreference = async () => { + if (!studentId) { + setIsLoading(false); + return; + } + + try { + const { data, error: fetchError } = await supabase + .from('students') + .select('uppercase_text_preferences') + .eq('id', studentId) + .single(); + + if (fetchError) throw fetchError; + + setIsUpperCase(data?.uppercase_text_preferences ?? false); + setError(null); + } catch (err) { + console.error('Erro ao carregar preferência de texto:', err); + setError('Não foi possível carregar sua preferência de texto'); + } finally { + setIsLoading(false); + } + }; + + loadPreference(); + }, [studentId]); + + const toggleUppercase = async () => { + if (!studentId || isLoading) return; + + try { + setIsLoading(true); + + const { error: updateError } = await supabase + .from('students') + .update({ uppercase_text_preferences: !isUpperCase }) + .eq('id', studentId); + + if (updateError) throw updateError; + + setIsUpperCase(!isUpperCase); + setError(null); + } catch (err) { + console.error('Erro ao atualizar preferência de texto:', err); + setError('Não foi possível atualizar sua preferência de texto'); + } finally { + setIsLoading(false); + } + }; + + return { + isUpperCase, + toggleUppercase, + isLoading, + error + }; +} \ No newline at end of file