feat: Implement mobile application and lead processing utilities.
This commit is contained in:
@@ -1,47 +1,69 @@
|
||||
import { TouchableOpacity, Text, ActivityIndicator } from 'react-native'
|
||||
import { Text, TouchableOpacity, ActivityIndicator } from 'react-native'
|
||||
import { cn } from '../../lib/utils'
|
||||
|
||||
interface ButtonProps {
|
||||
label: string
|
||||
onPress: () => void
|
||||
variant?: 'primary' | 'secondary' | 'ghost'
|
||||
variant?: 'primary' | 'secondary' | 'ghost' | 'destructive' | 'outline'
|
||||
size?: 'default' | 'sm' | 'lg'
|
||||
loading?: boolean
|
||||
disabled?: boolean
|
||||
icon?: string
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function Button({
|
||||
label,
|
||||
onPress,
|
||||
variant = 'primary',
|
||||
size = 'default',
|
||||
loading,
|
||||
disabled,
|
||||
icon,
|
||||
className,
|
||||
}: ButtonProps) {
|
||||
const base = 'rounded-2xl py-4 flex-row items-center justify-center gap-2'
|
||||
const variants = {
|
||||
primary: `${base} bg-brand-500`,
|
||||
secondary: `${base} bg-white border border-gray-200`,
|
||||
ghost: `${base}`,
|
||||
}
|
||||
const textVariants = {
|
||||
primary: 'text-white font-semibold text-base',
|
||||
secondary: 'text-gray-900 font-semibold text-base',
|
||||
ghost: 'text-brand-500 font-semibold text-base',
|
||||
}
|
||||
const isDisabled = disabled || loading
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={onPress}
|
||||
disabled={disabled || loading}
|
||||
className={`${variants[variant]} ${disabled || loading ? 'opacity-50' : ''}`}
|
||||
disabled={isDisabled}
|
||||
className={cn(
|
||||
'flex-row items-center justify-center rounded-xl',
|
||||
{
|
||||
'bg-primary shadow-sm': variant === 'primary',
|
||||
'bg-secondary border border-border': variant === 'secondary',
|
||||
'bg-transparent': variant === 'ghost',
|
||||
'bg-destructive': variant === 'destructive',
|
||||
'bg-background border border-input': variant === 'outline',
|
||||
|
||||
'h-10 px-4 py-2': size === 'default',
|
||||
'h-9 rounded-md px-3': size === 'sm',
|
||||
'h-11 rounded-md px-8': size === 'lg',
|
||||
|
||||
'opacity-50': isDisabled,
|
||||
},
|
||||
className
|
||||
)}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator color={variant === 'primary' ? 'white' : '#E63946'} />
|
||||
<ActivityIndicator
|
||||
color={variant === 'primary' || variant === 'destructive' ? 'white' : 'black'}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{icon && <Text className="text-xl">{icon}</Text>}
|
||||
<Text className={textVariants[variant]}>{label}</Text>
|
||||
</>
|
||||
<Text
|
||||
className={cn(
|
||||
'text-sm font-medium',
|
||||
{
|
||||
'text-primary-foreground': variant === 'primary',
|
||||
'text-secondary-foreground': variant === 'secondary',
|
||||
'text-primary': variant === 'ghost',
|
||||
'text-destructive-foreground': variant === 'destructive',
|
||||
'text-foreground': variant === 'outline',
|
||||
}
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user