mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-17 05:47:52 +00:00
feat: Adicionando transformação de texto para maiúsculo
This commit is contained in:
parent
a0cfccc14d
commit
7880ce8dda
89
src/components/ui/adaptive-text.tsx
Normal file
89
src/components/ui/adaptive-text.tsx
Normal file
@ -0,0 +1,89 @@
|
||||
import React from 'react';
|
||||
import { cn } from '../../lib/utils';
|
||||
|
||||
interface AdaptiveTextProps extends React.HTMLAttributes<HTMLSpanElement> {
|
||||
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) => (
|
||||
<AdaptiveText
|
||||
as="h1"
|
||||
className={cn(
|
||||
'text-2xl font-bold text-gray-900',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
export const AdaptiveParagraph = ({
|
||||
className,
|
||||
...props
|
||||
}: AdaptiveTextProps) => (
|
||||
<AdaptiveText
|
||||
as="p"
|
||||
className={cn(
|
||||
'text-base text-gray-700 leading-relaxed',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
export const AdaptiveLabel = ({
|
||||
className,
|
||||
...props
|
||||
}: AdaptiveTextProps) => (
|
||||
<AdaptiveText
|
||||
as="span"
|
||||
className={cn(
|
||||
'text-sm font-medium text-gray-600',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
// Hook para memoização de textos longos
|
||||
export function useAdaptiveText(text: string, isUpperCase: boolean) {
|
||||
return React.useMemo(
|
||||
() => isUpperCase ? text.toUpperCase() : text,
|
||||
[text, isUpperCase]
|
||||
);
|
||||
}
|
||||
40
src/components/ui/text-case-toggle.tsx
Normal file
40
src/components/ui/text-case-toggle.tsx
Normal file
@ -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 (
|
||||
<button
|
||||
onClick={onToggle}
|
||||
disabled={isLoading}
|
||||
className={cn(
|
||||
'flex items-center gap-2 px-3 py-1.5 rounded-lg transition-colors',
|
||||
'text-gray-600 hover:text-gray-900 hover:bg-gray-100',
|
||||
'border border-gray-200',
|
||||
'disabled:opacity-50 disabled:cursor-not-allowed',
|
||||
className
|
||||
)}
|
||||
title={isUpperCase ? 'Mudar para minúsculas' : 'Mudar para maiúsculas'}
|
||||
>
|
||||
<Type className="h-4 w-4" />
|
||||
<span className="text-sm font-medium select-none">
|
||||
{isUpperCase ? 'Aa' : 'AA'}
|
||||
</span>
|
||||
{isLoading && (
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
74
src/hooks/useUppercasePreference.ts
Normal file
74
src/hooks/useUppercasePreference.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { supabase } from '../lib/supabase';
|
||||
|
||||
interface UseUppercasePreferenceReturn {
|
||||
isUpperCase: boolean;
|
||||
toggleUppercase: () => Promise<void>;
|
||||
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<string | null>(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
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user