This commit is contained in:
2026-05-21 10:26:50 +01:00
parent 5cb96f0761
commit 8d5e706521
18 changed files with 662 additions and 496 deletions

View File

@@ -9,7 +9,7 @@ export default function App() {
<SafeAreaProvider>
<AppProvider>
<AppNavigator />
<StatusBar style="light" />
<StatusBar style="auto" />
</AppProvider>
</SafeAreaProvider>
);

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { View, Text, StyleSheet, ViewStyle } from 'react-native';
import { colors, radius } from '../../lib/theme';
type Props = {
children: React.ReactNode;
@@ -10,20 +11,20 @@ type Props = {
const colorMap = {
solid: {
amber: { bg: '#f59e0b', text: '#fff' },
slate: { bg: '#475569', text: '#fff' },
green: { bg: '#10b981', text: '#fff' },
red: { bg: '#ef4444', text: '#fff' },
blue: { bg: '#3b82f6', text: '#fff' },
indigo: { bg: '#6366f1', text: '#fff' },
amber: { bg: colors.accent, text: colors.textInverse },
slate: { bg: colors.textSoft, text: colors.textInverse },
green: { bg: colors.success, text: colors.textInverse },
red: { bg: colors.danger, text: colors.textInverse },
blue: { bg: colors.primary, text: colors.textInverse },
indigo: { bg: colors.primary, text: colors.textInverse },
},
soft: {
amber: { bg: '#fef3c7', text: '#92400e' },
slate: { bg: '#f1f5f9', text: '#475569' },
green: { bg: '#d1fae5', text: '#065f46' },
red: { bg: '#fee2e2', text: '#991b1b' },
blue: { bg: '#dbeafe', text: '#1e40af' },
indigo: { bg: '#e0e7ff', text: '#4338ca' },
amber: { bg: colors.accentSoft, text: '#7a4310' },
slate: { bg: colors.backgroundAlt, text: colors.textSoft },
green: { bg: colors.successSoft, text: '#166534' },
red: { bg: colors.dangerSoft, text: '#991b1b' },
blue: { bg: colors.primarySoft, text: colors.primaryDark },
indigo: { bg: colors.primarySoft, text: colors.primaryDark },
},
};
@@ -41,7 +42,7 @@ const styles = StyleSheet.create({
badge: {
paddingHorizontal: 10,
paddingVertical: 4,
borderRadius: 12,
borderRadius: radius.pill,
alignSelf: 'flex-start',
},
text: {
@@ -50,4 +51,3 @@ const styles = StyleSheet.create({
},
});

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { TouchableOpacity, Text, StyleSheet, ActivityIndicator, ViewStyle, TextStyle, StyleProp } from 'react-native';
import { colors, radius, shadows } from '../../lib/theme';
type Props = {
children: React.ReactNode;
@@ -36,7 +37,7 @@ export const Button = ({ children, onPress, variant = 'solid', size = 'md', disa
activeOpacity={0.7}
>
{loading ? (
<ActivityIndicator size="small" color={variant === 'solid' ? '#fff' : '#818cf8'} />
<ActivityIndicator size="small" color={variant === 'solid' ? colors.textInverse : colors.primary} />
) : (
<Text style={textStyles}>{children}</Text>
)}
@@ -46,18 +47,20 @@ export const Button = ({ children, onPress, variant = 'solid', size = 'md', disa
const styles = StyleSheet.create({
base: {
borderRadius: 14,
borderRadius: radius.md,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
minHeight: 44,
},
solid: {
backgroundColor: '#6366f1',
backgroundColor: colors.primary,
...shadows.soft,
},
outline: {
backgroundColor: 'transparent',
borderWidth: 1.5,
borderColor: 'rgba(99,102,241,0.4)',
borderWidth: 1,
borderColor: colors.borderStrong,
},
ghost: {
backgroundColor: 'transparent',
@@ -81,13 +84,13 @@ const styles = StyleSheet.create({
fontWeight: '700',
},
text_solid: {
color: '#fff',
color: colors.textInverse,
},
text_outline: {
color: '#a5b4fc',
color: colors.primaryDark,
},
text_ghost: {
color: '#a5b4fc',
color: colors.primaryDark,
},
textSize_sm: {
fontSize: 12,

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { View, StyleSheet, ViewStyle, StyleProp } from 'react-native';
import { colors, radius, shadows } from '../../lib/theme';
type Props = {
children: React.ReactNode;
@@ -12,10 +13,11 @@ export const Card = ({ children, style }: Props) => {
const styles = StyleSheet.create({
card: {
backgroundColor: '#141420',
borderRadius: 20,
backgroundColor: colors.surface,
borderRadius: radius.sm,
padding: 16,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.06)',
borderColor: colors.border,
...shadows.card,
},
});

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { TextInput, View, Text, StyleSheet, TextInputProps } from 'react-native';
import { colors, radius } from '../../lib/theme';
type Props = TextInputProps & {
label?: string;
@@ -12,7 +13,7 @@ export const Input = ({ label, error, style, ...props }: Props) => {
{label && <Text style={styles.label}>{label}</Text>}
<TextInput
style={[styles.input, error && styles.inputError, style]}
placeholderTextColor="#475569"
placeholderTextColor={colors.placeholder}
{...props}
/>
{error && <Text style={styles.error}>{error}</Text>}
@@ -27,27 +28,27 @@ const styles = StyleSheet.create({
label: {
fontSize: 12,
fontWeight: '700',
color: '#94a3b8',
color: colors.textMuted,
textTransform: 'uppercase',
letterSpacing: 0.5,
letterSpacing: 0,
marginBottom: 8,
},
input: {
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.08)',
borderRadius: 14,
borderColor: colors.border,
borderRadius: radius.md,
paddingHorizontal: 16,
paddingVertical: 14,
fontSize: 15,
color: '#f8fafc',
backgroundColor: '#1c1c2e',
color: colors.text,
backgroundColor: colors.surface,
},
inputError: {
borderColor: '#ef4444',
borderColor: colors.danger,
},
error: {
fontSize: 12,
color: '#ef4444',
color: colors.danger,
marginTop: 6,
},
});

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { colors, radius, shadows } from '../../lib/theme';
type Step = {
id: number;
@@ -69,14 +70,12 @@ export const Stepper = ({ steps, currentStep }: Props) => {
const styles = StyleSheet.create({
container: {
paddingVertical: 20,
backgroundColor: '#fff',
borderRadius: 16,
backgroundColor: colors.surface,
borderRadius: radius.sm,
marginBottom: 16,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.05,
shadowRadius: 2,
elevation: 2,
borderWidth: 1,
borderColor: colors.border,
...shadows.soft,
},
stepsWrapper: {
flexDirection: 'row',
@@ -94,44 +93,44 @@ const styles = StyleSheet.create({
width: 30,
height: 30,
borderRadius: 15,
backgroundColor: '#fff',
backgroundColor: colors.surface,
borderWidth: 2,
borderColor: '#e2e8f0',
borderColor: colors.borderStrong,
alignItems: 'center',
justifyContent: 'center',
marginBottom: 6,
},
circleActive: {
borderColor: '#6366f1',
backgroundColor: '#6366f1',
borderColor: colors.primary,
backgroundColor: colors.primary,
},
circleCompleted: {
borderColor: '#6366f1',
backgroundColor: '#6366f1',
borderColor: colors.primary,
backgroundColor: colors.primary,
},
stepNumber: {
fontSize: 12,
fontWeight: 'bold',
color: '#94a3b8',
color: colors.textSubtle,
},
stepNumberActive: {
color: '#fff',
color: colors.textInverse,
},
stepNumberCompleted: {
color: '#fff',
color: colors.textInverse,
},
label: {
fontSize: 9,
fontWeight: 'bold',
color: '#94a3b8',
color: colors.textSubtle,
textTransform: 'uppercase',
textAlign: 'center',
},
labelActive: {
color: '#6366f1',
color: colors.primary,
},
labelCompleted: {
color: '#6366f1',
color: colors.primary,
},
lineBackground: {
position: 'absolute',
@@ -139,7 +138,7 @@ const styles = StyleSheet.create({
left: 50, // approx center of first circle (20 padding + 60/2)
right: 50, // approx center of last circle
height: 2,
backgroundColor: '#e2e8f0',
backgroundColor: colors.border,
zIndex: 0,
},
lineProgress: {
@@ -148,7 +147,7 @@ const styles = StyleSheet.create({
left: 50,
// Width is controlled by style prop
height: 2,
backgroundColor: '#6366f1',
backgroundColor: colors.primary,
zIndex: 0,
maxWidth: '75%', // approx distance between first and last circle centers
},

88
src/lib/theme.ts Normal file
View File

@@ -0,0 +1,88 @@
import { Platform } from 'react-native';
export const colors = {
background: '#eef3ef',
backgroundAlt: '#e5ebe7',
surface: '#ffffff',
surfaceMuted: '#f7faf8',
surfaceDark: '#14211d',
surfaceDarkMuted: '#20312b',
text: '#17211d',
textSoft: '#35443e',
textMuted: '#64736d',
textSubtle: '#87948f',
textInverse: '#f8fbf8',
border: '#dce5df',
borderStrong: '#c8d5ce',
borderDark: 'rgba(255,255,255,0.12)',
primary: '#0f766e',
primaryDark: '#0b4f49',
primarySoft: '#d9f1ed',
accent: '#c87918',
accentSoft: '#fff1d1',
success: '#16a34a',
successSoft: '#dcfce7',
danger: '#dc2626',
dangerSoft: '#fee2e2',
warning: '#d97706',
warningSoft: '#fef3c7',
star: '#f2a51a',
overlay: 'rgba(12,20,17,0.56)',
placeholder: '#8a9791',
};
export const radius = {
xs: 6,
sm: 8,
md: 10,
lg: 12,
xl: 16,
pill: 999,
};
export const spacing = {
screen: 20,
};
const cardShadow = Platform.select({
ios: {
shadowColor: '#102018',
shadowOffset: { width: 0, height: 8 },
shadowOpacity: 0.08,
shadowRadius: 18,
},
android: {
elevation: 3,
},
default: {
shadowColor: '#102018',
shadowOffset: { width: 0, height: 8 },
shadowOpacity: 0.08,
shadowRadius: 18,
elevation: 3,
},
}) ?? {};
const softShadow = Platform.select({
ios: {
shadowColor: '#102018',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.06,
shadowRadius: 12,
},
android: {
elevation: 2,
},
default: {
shadowColor: '#102018',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.06,
shadowRadius: 12,
elevation: 2,
},
}) ?? {};
export const shadows = {
card: cardShadow,
soft: softShadow,
};

View File

@@ -4,6 +4,7 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { View, Text, StyleSheet, Platform } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { colors, radius } from '../lib/theme';
import { useApp } from '../context/AppContext';
import AuthLogin from '../pages/AuthLogin';
import AuthRegister from '../pages/AuthRegister';
@@ -23,7 +24,7 @@ const TabIcon = ({ name, focused }: { name: any; focused: boolean }) => (
<Ionicons
name={focused ? name : `${name}-outline`}
size={20}
color={focused ? '#a5b4fc' : '#475569'}
color={focused ? colors.textInverse : '#9cad9f'}
/>
</View>
);
@@ -31,7 +32,7 @@ const TabIcon = ({ name, focused }: { name: any; focused: boolean }) => (
/* ── Client Tab Stacks ── */
function ExploreStack() {
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Navigator id="ExploreStack" screenOptions={{ headerShown: false }}>
<Stack.Screen name="Explore" component={Explore} />
<Stack.Screen name="ShopDetails" component={ShopDetails} />
<Stack.Screen name="Booking" component={Booking} />
@@ -41,7 +42,7 @@ function ExploreStack() {
function CartStack() {
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Navigator id="CartStack" screenOptions={{ headerShown: false }}>
<Stack.Screen name="Cart" component={Cart} />
</Stack.Navigator>
);
@@ -49,7 +50,7 @@ function CartStack() {
function ClientProfileStack() {
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Navigator id="ClientProfileStack" screenOptions={{ headerShown: false }}>
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="EventsCreate" component={EventsCreate} />
<Stack.Screen name="ShopDetails" component={ShopDetails} />
@@ -62,11 +63,12 @@ function ClientTabs() {
const { cart } = useApp();
return (
<Tab.Navigator
id="ClientTabs"
screenOptions={{
headerShown: false,
tabBarStyle: tabStyles.bar,
tabBarActiveTintColor: '#a5b4fc',
tabBarInactiveTintColor: '#475569',
tabBarActiveTintColor: colors.textInverse,
tabBarInactiveTintColor: '#9cad9f',
tabBarLabelStyle: tabStyles.label,
}}
>
@@ -103,7 +105,7 @@ function ClientTabs() {
/* ── Barbearia Tab Stacks ── */
function DashboardStack() {
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Navigator id="DashboardStack" screenOptions={{ headerShown: false }}>
<Stack.Screen name="Dashboard" component={Dashboard} />
<Stack.Screen name="EventsCreate" component={EventsCreate} />
</Stack.Navigator>
@@ -112,7 +114,7 @@ function DashboardStack() {
function BarberProfileStack() {
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Navigator id="BarberProfileStack" screenOptions={{ headerShown: false }}>
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="EventsCreate" component={EventsCreate} />
</Stack.Navigator>
@@ -122,11 +124,12 @@ function BarberProfileStack() {
function BarbeariaTabs() {
return (
<Tab.Navigator
id="BarbeariaTabs"
screenOptions={{
headerShown: false,
tabBarStyle: tabStyles.bar,
tabBarActiveTintColor: '#a5b4fc',
tabBarInactiveTintColor: '#475569',
tabBarActiveTintColor: colors.textInverse,
tabBarInactiveTintColor: '#9cad9f',
tabBarLabelStyle: tabStyles.label,
}}
>
@@ -158,9 +161,10 @@ export default function AppNavigator() {
<NavigationContainer>
{!user ? (
<Stack.Navigator
id="RootStack"
screenOptions={{
headerStyle: { backgroundColor: '#0a0a0f' },
headerTintColor: '#f8fafc',
headerStyle: { backgroundColor: colors.surfaceDark },
headerTintColor: colors.textInverse,
headerTitleStyle: { fontWeight: '700' },
}}
>
@@ -180,8 +184,8 @@ export default function AppNavigator() {
const tabStyles = StyleSheet.create({
bar: {
backgroundColor: '#0a0a0f',
borderTopColor: 'rgba(255,255,255,0.06)',
backgroundColor: colors.surfaceDark,
borderTopColor: colors.borderDark,
borderTopWidth: 1,
height: Platform.OS === 'ios' ? 88 : 64,
paddingBottom: Platform.OS === 'ios' ? 28 : 8,
@@ -190,11 +194,11 @@ const tabStyles = StyleSheet.create({
label: {
fontSize: 10,
fontWeight: '700',
letterSpacing: 0.5,
letterSpacing: 0,
},
badge: {
backgroundColor: '#6366f1',
color: '#fff',
backgroundColor: colors.accent,
color: colors.textInverse,
fontSize: 10,
fontWeight: '800',
minWidth: 18,
@@ -207,15 +211,15 @@ const iconStyles = StyleSheet.create({
wrap: {
width: 32,
height: 32,
borderRadius: 10,
borderRadius: radius.md,
alignItems: 'center',
justifyContent: 'center',
},
wrapActive: {
backgroundColor: 'rgba(99,102,241,0.15)',
backgroundColor: colors.primary,
},
emoji: {
fontSize: 18,
color: '#94a3b8',
color: '#9cad9f',
},
});

View File

@@ -7,6 +7,7 @@ import { useApp } from '../context/AppContext';
import { Button } from '../components/ui/Button';
import { Input } from '../components/ui/Input';
import { RootStackParamList } from '../navigation/types';
import { colors, radius, shadows } from '../lib/theme';
export default function AuthLogin() {
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
@@ -99,67 +100,78 @@ export default function AuthLogin() {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0a0a0f',
backgroundColor: colors.background,
},
content: {
padding: 24,
padding: 20,
justifyContent: 'center',
minHeight: '100%',
},
logoRow: {
alignItems: 'center',
marginBottom: 32,
marginBottom: 28,
backgroundColor: colors.surface,
borderRadius: radius.sm,
borderWidth: 1,
borderColor: colors.border,
paddingVertical: 18,
...shadows.card,
},
logoImage: {
width: 280,
height: 140,
width: 240,
height: 100,
},
title: {
fontSize: 34,
fontSize: 32,
fontWeight: '900',
color: '#f8fafc',
color: colors.text,
textAlign: 'center',
marginBottom: 6,
},
subtitle: {
fontSize: 15,
color: '#64748b',
color: colors.textMuted,
marginBottom: 32,
textAlign: 'center',
fontWeight: '500',
},
errorBox: {
backgroundColor: 'rgba(239,68,68,0.1)',
borderColor: 'rgba(239,68,68,0.3)',
backgroundColor: colors.dangerSoft,
borderColor: '#fecaca',
borderWidth: 1,
borderRadius: 14,
borderRadius: radius.md,
padding: 14,
marginBottom: 16,
},
errorText: {
color: '#fca5a5',
color: '#991b1b',
fontWeight: '600',
fontSize: 13,
},
submitButton: {
width: '100%',
marginTop: 4,
backgroundColor: '#6366f1',
backgroundColor: colors.primary,
paddingVertical: 16,
},
guestButton: {
alignSelf: 'center',
marginTop: 16,
paddingVertical: 10,
paddingHorizontal: 16,
borderRadius: radius.pill,
backgroundColor: colors.surface,
borderWidth: 1,
borderColor: colors.border,
},
guestText: {
color: '#64748b',
color: colors.primaryDark,
fontWeight: '700',
fontSize: 14,
},
divider: {
height: 1,
backgroundColor: 'rgba(255,255,255,0.06)',
backgroundColor: colors.border,
marginVertical: 24,
},
footer: {
@@ -169,11 +181,11 @@ const styles = StyleSheet.create({
},
footerText: {
fontSize: 14,
color: '#64748b',
color: colors.textMuted,
},
footerLink: {
fontSize: 14,
color: '#818cf8',
color: colors.primaryDark,
fontWeight: '800',
},
});

View File

@@ -7,6 +7,7 @@ import { useApp } from '../context/AppContext';
import { Button } from '../components/ui/Button';
import { Input } from '../components/ui/Input';
import { RootStackParamList } from '../navigation/types';
import { colors, radius, shadows } from '../lib/theme';
export default function AuthRegister() {
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
@@ -126,54 +127,60 @@ export default function AuthRegister() {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0a0a0f',
backgroundColor: colors.background,
},
content: {
padding: 24,
padding: 20,
justifyContent: 'center',
minHeight: '100%',
},
logoRow: {
alignItems: 'center',
marginBottom: 28,
marginBottom: 24,
backgroundColor: colors.surface,
borderRadius: radius.sm,
borderWidth: 1,
borderColor: colors.border,
paddingVertical: 16,
...shadows.card,
},
logoImage: {
width: 200,
height: 100,
width: 220,
height: 90,
},
title: {
fontSize: 34,
fontSize: 32,
fontWeight: '900',
color: '#f8fafc',
color: colors.text,
textAlign: 'center',
marginBottom: 6,
},
subtitle: {
fontSize: 15,
color: '#64748b',
color: colors.textMuted,
marginBottom: 28,
textAlign: 'center',
fontWeight: '500',
},
errorBox: {
backgroundColor: 'rgba(239,68,68,0.1)',
borderColor: 'rgba(239,68,68,0.3)',
backgroundColor: colors.dangerSoft,
borderColor: '#fecaca',
borderWidth: 1,
borderRadius: 14,
borderRadius: radius.md,
padding: 14,
marginBottom: 16,
},
errorText: {
color: '#fca5a5',
color: '#991b1b',
fontWeight: '600',
fontSize: 13,
},
label: {
fontSize: 12,
color: '#94a3b8',
color: colors.textMuted,
fontWeight: '700',
textTransform: 'uppercase',
letterSpacing: 0.5,
letterSpacing: 0,
marginBottom: 10,
},
roleContainer: {
@@ -184,16 +191,17 @@ const styles = StyleSheet.create({
roleButton: {
flex: 1,
padding: 18,
borderRadius: 16,
borderWidth: 1.5,
borderColor: 'rgba(255,255,255,0.06)',
backgroundColor: '#141420',
borderRadius: radius.sm,
borderWidth: 1,
borderColor: colors.border,
backgroundColor: colors.surface,
alignItems: 'center',
gap: 8,
...shadows.soft,
},
roleButtonActive: {
borderColor: '#6366f1',
backgroundColor: 'rgba(99,102,241,0.1)',
borderColor: colors.primary,
backgroundColor: colors.primarySoft,
},
roleEmoji: {
fontSize: 24,
@@ -201,21 +209,21 @@ const styles = StyleSheet.create({
roleText: {
fontSize: 13,
fontWeight: '800',
color: '#64748b',
color: colors.textMuted,
textTransform: 'uppercase',
},
roleTextActive: {
color: '#a5b4fc',
color: colors.primaryDark,
},
submitButton: {
width: '100%',
marginTop: 4,
backgroundColor: '#6366f1',
backgroundColor: colors.primary,
paddingVertical: 16,
},
divider: {
height: 1,
backgroundColor: 'rgba(255,255,255,0.06)',
backgroundColor: colors.border,
marginVertical: 24,
},
footer: {
@@ -225,11 +233,11 @@ const styles = StyleSheet.create({
},
footerText: {
fontSize: 14,
color: '#64748b',
color: colors.textMuted,
},
footerLink: {
fontSize: 14,
color: '#818cf8',
color: colors.primaryDark,
fontWeight: '800',
},
});

View File

@@ -6,6 +6,7 @@ import { useApp } from '../context/AppContext';
import { Card } from '../components/ui/Card';
import { Button } from '../components/ui/Button';
import { currency } from '../lib/format';
import { colors, radius, shadows } from '../lib/theme';
export default function Booking() {
const route = useRoute();
@@ -185,25 +186,30 @@ export default function Booking() {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0a0a0f',
backgroundColor: colors.background,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 20,
paddingVertical: 10,
paddingVertical: 12,
backgroundColor: colors.surface,
borderBottomWidth: 1,
borderBottomColor: colors.border,
},
backBtn: {
width: 40,
height: 40,
borderRadius: 12,
backgroundColor: '#141420',
borderRadius: radius.md,
backgroundColor: colors.surfaceMuted,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: colors.border,
},
backIcon: {
color: '#f8fafc',
color: colors.text,
fontSize: 20,
fontWeight: '700',
},
@@ -211,12 +217,12 @@ const styles = StyleSheet.create({
alignItems: 'center',
},
headerTitle: {
color: '#f8fafc',
color: colors.text,
fontSize: 18,
fontWeight: '800',
},
headerSubtitle: {
color: '#64748b',
color: colors.textMuted,
fontSize: 12,
fontWeight: '600',
},
@@ -228,11 +234,11 @@ const styles = StyleSheet.create({
gap: 12,
},
stepLabel: {
color: '#94a3b8',
color: colors.textMuted,
fontSize: 12,
fontWeight: '800',
textTransform: 'uppercase',
letterSpacing: 1,
letterSpacing: 0,
marginBottom: 8,
},
choiceCard: {
@@ -240,37 +246,37 @@ const styles = StyleSheet.create({
alignItems: 'center',
padding: 16,
gap: 14,
borderWidth: 1.5,
borderColor: 'transparent',
borderWidth: 1,
borderColor: colors.border,
},
choiceCardActive: {
borderColor: '#6366f1',
backgroundColor: 'rgba(99,102,241,0.05)',
borderColor: colors.primary,
backgroundColor: colors.primarySoft,
},
choiceName: {
color: '#f8fafc',
color: colors.text,
fontSize: 16,
fontWeight: '700',
},
choiceMeta: {
color: '#64748b',
color: colors.textMuted,
fontSize: 13,
},
choicePrice: {
color: '#f8fafc',
color: colors.primaryDark,
fontSize: 16,
fontWeight: '800',
},
avatarMini: {
width: 44,
height: 44,
borderRadius: 14,
backgroundColor: '#1c1c2e',
borderRadius: radius.md,
backgroundColor: colors.primarySoft,
alignItems: 'center',
justifyContent: 'center',
},
avatarTxt: {
color: '#6366f1',
color: colors.primary,
fontSize: 18,
fontWeight: '900',
},
@@ -280,30 +286,31 @@ const styles = StyleSheet.create({
dateItem: {
width: 64,
height: 80,
borderRadius: 16,
backgroundColor: '#141420',
borderRadius: radius.sm,
backgroundColor: colors.surface,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.06)',
borderColor: colors.border,
...shadows.soft,
},
dateItemActive: {
backgroundColor: '#6366f1',
borderColor: '#6366f1',
backgroundColor: colors.primary,
borderColor: colors.primary,
},
dateWeek: {
color: '#475569',
color: colors.textMuted,
fontSize: 10,
fontWeight: '800',
},
dateDay: {
color: '#f8fafc',
color: colors.text,
fontSize: 20,
fontWeight: '900',
marginTop: 4,
},
dateTextActive: {
color: '#fff',
color: colors.textInverse,
},
slotsGrid: {
flexDirection: 'row',
@@ -313,27 +320,27 @@ const styles = StyleSheet.create({
slotItem: {
width: '22.5%',
height: 44,
borderRadius: 12,
backgroundColor: '#141420',
borderRadius: radius.md,
backgroundColor: colors.surface,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.06)',
borderColor: colors.border,
},
slotActive: {
backgroundColor: '#6366f1',
borderColor: '#6366f1',
backgroundColor: colors.primary,
borderColor: colors.primary,
},
slotBooked: {
opacity: 0.2,
},
slotText: {
color: '#94a3b8',
color: colors.textMuted,
fontSize: 14,
fontWeight: '700',
},
slotTextActive: {
color: '#fff',
color: colors.textInverse,
},
slotTextBooked: {
textDecorationLine: 'line-through',
@@ -347,21 +354,21 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
},
summaryLabel: {
color: '#64748b',
color: colors.textMuted,
fontSize: 14,
},
summaryValue: {
color: '#f8fafc',
color: colors.text,
fontSize: 14,
fontWeight: '700',
},
divider: {
height: 1,
backgroundColor: 'rgba(255,255,255,0.06)',
backgroundColor: colors.border,
marginVertical: 4,
},
summaryTotal: {
color: '#a5b4fc',
color: colors.primary,
fontSize: 22,
fontWeight: '900',
},
@@ -372,22 +379,22 @@ const styles = StyleSheet.create({
notifBtn: {
flex: 1,
paddingVertical: 12,
borderRadius: 12,
backgroundColor: '#141420',
borderRadius: radius.md,
backgroundColor: colors.surface,
alignItems: 'center',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.06)',
borderColor: colors.border,
},
notifBtnActive: {
backgroundColor: 'rgba(99,102,241,0.15)',
borderColor: '#6366f1',
backgroundColor: colors.primarySoft,
borderColor: colors.primary,
},
notifBtnTxt: {
color: '#64748b',
color: colors.textMuted,
fontSize: 12,
fontWeight: '700',
},
notifBtnTxtActive: {
color: '#a5b4fc',
color: colors.primaryDark,
},
});

View File

@@ -5,6 +5,7 @@ import { useNavigation } from '@react-navigation/native';
import { useApp } from '../context/AppContext';
import { Button } from '../components/ui/Button';
import { currency } from '../lib/format';
import { colors, radius, shadows } from '../lib/theme';
export default function Cart() {
const navigation = useNavigation();
@@ -122,7 +123,7 @@ export default function Cart() {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0a0a0f',
backgroundColor: colors.background,
},
content: {
padding: 20,
@@ -132,7 +133,7 @@ const styles = StyleSheet.create({
title: {
fontSize: 32,
fontWeight: '900',
color: '#f8fafc',
color: colors.text,
marginBottom: 8,
},
emptyState: {
@@ -147,22 +148,23 @@ const styles = StyleSheet.create({
marginBottom: 8,
},
emptyTitle: {
color: '#f8fafc',
color: colors.text,
fontSize: 22,
fontWeight: '800',
},
emptyText: {
color: '#64748b',
color: colors.textMuted,
fontSize: 15,
textAlign: 'center',
},
shopCard: {
backgroundColor: '#141420',
borderRadius: 24,
backgroundColor: colors.surface,
borderRadius: radius.sm,
padding: 20,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.06)',
borderColor: colors.border,
marginBottom: 16,
...shadows.card,
},
shopHeader: {
flexDirection: 'row',
@@ -172,29 +174,29 @@ const styles = StyleSheet.create({
shopIcon: {
width: 48,
height: 48,
borderRadius: 16,
backgroundColor: 'rgba(99,102,241,0.12)',
borderRadius: radius.md,
backgroundColor: colors.primarySoft,
alignItems: 'center',
justifyContent: 'center',
},
shopIconText: {
color: '#818cf8',
color: colors.primary,
fontSize: 18,
fontWeight: '900',
},
shopName: {
fontSize: 18,
fontWeight: '800',
color: '#f8fafc',
color: colors.text,
},
shopAddress: {
fontSize: 13,
color: '#475569',
color: colors.textMuted,
marginTop: 2,
},
divider: {
height: 1,
backgroundColor: 'rgba(255,255,255,0.06)',
backgroundColor: colors.border,
marginVertical: 16,
},
item: {
@@ -209,14 +211,14 @@ const styles = StyleSheet.create({
},
typePill: {
alignSelf: 'flex-start',
backgroundColor: 'rgba(99,102,241,0.1)',
borderRadius: 8,
backgroundColor: colors.primarySoft,
borderRadius: radius.pill,
paddingHorizontal: 10,
paddingVertical: 3,
marginBottom: 4,
},
typeText: {
color: '#818cf8',
color: colors.primaryDark,
fontSize: 10,
fontWeight: '800',
textTransform: 'uppercase',
@@ -224,24 +226,24 @@ const styles = StyleSheet.create({
itemName: {
fontSize: 16,
fontWeight: '700',
color: '#f8fafc',
color: colors.text,
},
itemQty: {
fontSize: 13,
color: '#64748b',
color: colors.textMuted,
fontWeight: '500',
},
removeBtn: {
width: 36,
height: 36,
borderRadius: 12,
backgroundColor: 'rgba(239,68,68,0.08)',
borderRadius: radius.md,
backgroundColor: colors.dangerSoft,
alignItems: 'center',
justifyContent: 'center',
marginLeft: 12,
},
removeText: {
color: '#ef4444',
color: colors.danger,
fontSize: 14,
fontWeight: '800',
},
@@ -252,20 +254,20 @@ const styles = StyleSheet.create({
marginBottom: 20,
},
totalLabel: {
color: '#94a3b8',
color: colors.textMuted,
fontSize: 14,
fontWeight: '700',
textTransform: 'uppercase',
letterSpacing: 1,
letterSpacing: 0,
},
totalValue: {
color: '#a5b4fc',
color: colors.primary,
fontSize: 26,
fontWeight: '900',
},
checkoutBtn: {
backgroundColor: '#6366f1',
borderRadius: 16,
backgroundColor: colors.primary,
borderRadius: radius.md,
paddingVertical: 16,
},
});

View File

@@ -8,14 +8,15 @@ import { Card } from '../components/ui/Card';
import { Button } from '../components/ui/Button';
import { currency } from '../lib/format';
import { supabase } from '../lib/supabase';
import { colors, radius, shadows } from '../lib/theme';
type Tab = 'agenda' | 'servicos' | 'produtos' | 'equipa' | 'perfil';
const statusColor: Record<string, string> = {
pendente: '#6366f1',
confirmado: '#10b981',
concluido: '#10b981',
cancelado: '#ef4444',
pendente: colors.primary,
confirmado: colors.success,
concluido: colors.success,
cancelado: colors.danger,
};
const statusLabel: Record<string, string> = {
@@ -203,7 +204,7 @@ export default function Dashboard() {
value={dateFilter}
onChangeText={setDateFilter}
placeholder="AAAA-MM-DD"
placeholderTextColor="#475569"
placeholderTextColor={colors.placeholder}
style={styles.dateInput}
/>
</View>
@@ -231,8 +232,8 @@ export default function Dashboard() {
</TouchableOpacity>
)}
{appt.status !== 'cancelado' && appt.status !== 'concluido' && (
<TouchableOpacity onPress={() => updateAppointmentStatus(appt.id, 'cancelado')} style={[styles.premiumActionBtn, { backgroundColor: 'rgba(239,68,68,0.1)' }]}>
<Text style={[styles.premiumActionBtnTxt, { color: '#ef4444' }]}>Cancelar</Text>
<TouchableOpacity onPress={() => updateAppointmentStatus(appt.id, 'cancelado')} style={[styles.premiumActionBtn, { backgroundColor: colors.dangerSoft, borderColor: '#fecaca' }]}>
<Text style={[styles.premiumActionBtnTxt, { color: colors.danger }]}>Cancelar</Text>
</TouchableOpacity>
)}
</View>
@@ -265,10 +266,10 @@ export default function Dashboard() {
<Card style={styles.formCard}>
<Text style={styles.formTitle}>Novo Serviço</Text>
<TextInput style={styles.input} placeholder="Nome do serviço" placeholderTextColor="#475569" value={formSvc.name} onChangeText={t => setFormSvc({...formSvc, name: t})} />
<TextInput style={styles.input} placeholder="Nome do serviço" placeholderTextColor={colors.placeholder} value={formSvc.name} onChangeText={t => setFormSvc({...formSvc, name: t})} />
<View style={styles.row}>
<TextInput style={[styles.input, {flex: 1}]} placeholder="Preço (€)" placeholderTextColor="#475569" keyboardType="numeric" value={formSvc.price} onChangeText={t => setFormSvc({...formSvc, price: t})} />
<TextInput style={[styles.input, {flex: 1}]} placeholder="Duração (min)" placeholderTextColor="#475569" keyboardType="numeric" value={formSvc.duration} onChangeText={t => setFormSvc({...formSvc, duration: t})} />
<TextInput style={[styles.input, {flex: 1}]} placeholder="Preço (€)" placeholderTextColor={colors.placeholder} keyboardType="numeric" value={formSvc.price} onChangeText={t => setFormSvc({...formSvc, price: t})} />
<TextInput style={[styles.input, {flex: 1}]} placeholder="Duração (min)" placeholderTextColor={colors.placeholder} keyboardType="numeric" value={formSvc.duration} onChangeText={t => setFormSvc({...formSvc, duration: t})} />
</View>
<Button size="sm" onPress={async () => {
try {
@@ -315,10 +316,10 @@ export default function Dashboard() {
<Card style={styles.formCard}>
<Text style={styles.formTitle}>Novo Produto</Text>
<TextInput style={styles.input} placeholder="Nome do produto" placeholderTextColor="#475569" value={formProd.name} onChangeText={t => setFormProd({...formProd, name: t})} />
<TextInput style={styles.input} placeholder="Nome do produto" placeholderTextColor={colors.placeholder} value={formProd.name} onChangeText={t => setFormProd({...formProd, name: t})} />
<View style={styles.row}>
<TextInput style={[styles.input, {flex: 1}]} placeholder="Preço (€)" placeholderTextColor="#475569" keyboardType="numeric" value={formProd.price} onChangeText={t => setFormProd({...formProd, price: t})} />
<TextInput style={[styles.input, {flex: 1}]} placeholder="Stock" placeholderTextColor="#475569" keyboardType="numeric" value={formProd.stock} onChangeText={t => setFormProd({...formProd, stock: t})} />
<TextInput style={[styles.input, {flex: 1}]} placeholder="Preço (€)" placeholderTextColor={colors.placeholder} keyboardType="numeric" value={formProd.price} onChangeText={t => setFormProd({...formProd, price: t})} />
<TextInput style={[styles.input, {flex: 1}]} placeholder="Stock" placeholderTextColor={colors.placeholder} keyboardType="numeric" value={formProd.stock} onChangeText={t => setFormProd({...formProd, stock: t})} />
</View>
<Button size="sm" onPress={async () => {
try {
@@ -353,8 +354,8 @@ export default function Dashboard() {
<Card style={styles.formCard}>
<Text style={styles.formTitle}>Novo Profissional</Text>
<TextInput style={styles.input} placeholder="Nome do profissional" placeholderTextColor="#475569" value={formBarb.name} onChangeText={t => setFormBarb({...formBarb, name: t})} />
<TextInput style={styles.input} placeholder="Especialidades (separadas por vírgula)" placeholderTextColor="#475569" value={formBarb.specialties} onChangeText={t => setFormBarb({...formBarb, specialties: t})} />
<TextInput style={styles.input} placeholder="Nome do profissional" placeholderTextColor={colors.placeholder} value={formBarb.name} onChangeText={t => setFormBarb({...formBarb, name: t})} />
<TextInput style={styles.input} placeholder="Especialidades (separadas por vírgula)" placeholderTextColor={colors.placeholder} value={formBarb.specialties} onChangeText={t => setFormBarb({...formBarb, specialties: t})} />
<Button size="sm" onPress={async () => {
try {
await addBarber(shop.id, {
@@ -386,17 +387,17 @@ export default function Dashboard() {
<Card style={styles.formCard}>
<Text style={styles.inputLabel}>Informação Geral</Text>
<TextInput style={styles.input} placeholder="Nome da Barbearia" placeholderTextColor="#475569" value={shopName} onChangeText={setShopName} />
<TextInput style={styles.input} placeholder="Endereço Completo" placeholderTextColor="#475569" value={shopAddr} onChangeText={setShopAddr} />
<TextInput style={styles.input} placeholder="Telefone de Contacto" placeholderTextColor="#475569" value={phone1} onChangeText={setPhone1} keyboardType="phone-pad" />
<TextInput style={styles.input} placeholder="Nome da Barbearia" placeholderTextColor={colors.placeholder} value={shopName} onChangeText={setShopName} />
<TextInput style={styles.input} placeholder="Endereço Completo" placeholderTextColor={colors.placeholder} value={shopAddr} onChangeText={setShopAddr} />
<TextInput style={styles.input} placeholder="Telefone de Contacto" placeholderTextColor={colors.placeholder} value={phone1} onChangeText={setPhone1} keyboardType="phone-pad" />
<Text style={[styles.inputLabel, { marginTop: 12 }]}>Redes Sociais</Text>
<TextInput style={styles.input} placeholder="WhatsApp (ex: 351912345678)" placeholderTextColor="#475569" value={whatsapp} onChangeText={setWhatsapp} />
<TextInput style={styles.input} placeholder="Instagram (User)" placeholderTextColor="#475569" value={instagram} onChangeText={setInstagram} />
<TextInput style={styles.input} placeholder="Facebook (Link)" placeholderTextColor="#475569" value={facebook} onChangeText={setFacebook} />
<TextInput style={styles.input} placeholder="WhatsApp (ex: 351912345678)" placeholderTextColor={colors.placeholder} value={whatsapp} onChangeText={setWhatsapp} />
<TextInput style={styles.input} placeholder="Instagram (User)" placeholderTextColor={colors.placeholder} value={instagram} onChangeText={setInstagram} />
<TextInput style={styles.input} placeholder="Facebook (Link)" placeholderTextColor={colors.placeholder} value={facebook} onChangeText={setFacebook} />
<Text style={[styles.inputLabel, { marginTop: 12 }]}>Pagamentos</Text>
<TextInput style={styles.input} placeholder="Métodos (ex: Dinheiro, MBWay, Cartão)" placeholderTextColor="#475569" value={paymentMethods} onChangeText={setPaymentMethods} />
<TextInput style={styles.input} placeholder="Métodos (ex: Dinheiro, MBWay, Cartão)" placeholderTextColor={colors.placeholder} value={paymentMethods} onChangeText={setPaymentMethods} />
<Text style={[styles.inputLabel, { marginTop: 12 }]}>Horário de Funcionamento</Text>
{schedule.map((s, idx) => (
@@ -425,7 +426,7 @@ export default function Dashboard() {
setSchedule(next);
}}
/>
<Text style={{ color: '#475569' }}>-</Text>
<Text style={{ color: colors.textSubtle }}>-</Text>
<TextInput
style={styles.timeInput}
value={s.close}
@@ -460,7 +461,7 @@ export default function Dashboard() {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0a0a0f',
backgroundColor: colors.background,
},
header: {
flexDirection: 'row',
@@ -468,6 +469,9 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
paddingHorizontal: 20,
paddingVertical: 16,
backgroundColor: colors.surface,
borderBottomWidth: 1,
borderBottomColor: colors.border,
},
headerLogo: {
width: 140,
@@ -476,41 +480,47 @@ const styles = StyleSheet.create({
brandPill: {
width: 44,
height: 44,
borderRadius: 14,
backgroundColor: '#141420',
borderRadius: radius.md,
backgroundColor: colors.primarySoft,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: 'rgba(99,102,241,0.3)',
borderColor: colors.border,
},
brandText: {
color: '#818cf8',
color: colors.primary,
fontSize: 18,
fontWeight: '900',
},
tabContainer: {
backgroundColor: '#141420',
paddingVertical: 4,
backgroundColor: colors.surface,
paddingVertical: 8,
borderBottomWidth: 1,
borderBottomColor: colors.border,
},
tabsScroll: {
paddingHorizontal: 20,
gap: 16,
gap: 8,
},
tabItem: {
paddingVertical: 14,
borderBottomWidth: 2,
borderBottomColor: 'transparent',
paddingVertical: 10,
paddingHorizontal: 14,
borderRadius: radius.pill,
borderWidth: 1,
borderColor: colors.border,
backgroundColor: colors.surfaceMuted,
},
tabItemActive: {
borderBottomColor: '#6366f1',
backgroundColor: colors.primary,
borderColor: colors.primary,
},
tabText: {
color: '#475569',
color: colors.textMuted,
fontSize: 14,
fontWeight: '700',
},
tabTextActive: {
color: '#f8fafc',
color: colors.textInverse,
},
content: {
padding: 20,
@@ -525,20 +535,20 @@ const styles = StyleSheet.create({
alignItems: 'center',
},
sectionTitle: {
color: '#f8fafc',
color: colors.text,
fontSize: 18,
fontWeight: '800',
},
dateInput: {
backgroundColor: '#141420',
borderRadius: 10,
backgroundColor: colors.surface,
borderRadius: radius.md,
paddingHorizontal: 12,
paddingVertical: 6,
color: '#f8fafc',
color: colors.text,
fontSize: 13,
fontWeight: '700',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.06)',
borderColor: colors.border,
},
agendaTicket: {
flexDirection: 'row',
@@ -548,13 +558,13 @@ const styles = StyleSheet.create({
},
ticketSide: {
width: 70,
backgroundColor: '#1c1c2e',
backgroundColor: colors.primarySoft,
alignItems: 'center',
justifyContent: 'center',
gap: 8,
},
ticketTime: {
color: '#f8fafc',
color: colors.primaryDark,
fontSize: 18,
fontWeight: '900',
},
@@ -574,17 +584,17 @@ const styles = StyleSheet.create({
alignItems: 'center',
},
ticketSvc: {
color: '#f8fafc',
color: colors.text,
fontSize: 16,
fontWeight: '800',
},
ticketPrice: {
color: '#a5b4fc',
color: colors.primary,
fontSize: 15,
fontWeight: '800',
},
ticketMeta: {
color: '#64748b',
color: colors.textMuted,
fontSize: 12,
marginTop: 4,
},
@@ -594,31 +604,31 @@ const styles = StyleSheet.create({
marginTop: 12,
},
premiumActionBtn: {
backgroundColor: 'rgba(16,185,129,0.1)',
backgroundColor: colors.successSoft,
paddingHorizontal: 16,
paddingVertical: 8,
borderRadius: 12,
borderRadius: radius.pill,
borderWidth: 1,
borderColor: 'rgba(16,185,129,0.2)',
borderColor: '#bbf7d0',
},
premiumActionBtnTxt: {
color: '#10b981',
color: '#166534',
fontSize: 12,
fontWeight: '800',
textTransform: 'uppercase',
letterSpacing: 0.5,
letterSpacing: 0,
},
emptyBox: {
alignItems: 'center',
padding: 40,
backgroundColor: '#141420',
borderRadius: 20,
backgroundColor: colors.surface,
borderRadius: radius.sm,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.06)',
borderColor: colors.border,
borderStyle: 'dashed',
},
emptyTxt: {
color: '#475569',
color: colors.textMuted,
fontSize: 14,
fontWeight: '600',
},
@@ -627,29 +637,29 @@ const styles = StyleSheet.create({
alignItems: 'center',
gap: 14,
padding: 14,
backgroundColor: '#141420',
borderRadius: 16,
backgroundColor: colors.surface,
borderRadius: radius.sm,
marginBottom: 12,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.03)',
borderColor: colors.border,
},
itemInfo: {
flex: 1,
},
itemName: {
color: '#f8fafc',
color: colors.text,
fontSize: 16,
fontWeight: '800',
},
itemMeta: {
color: '#64748b',
color: colors.textMuted,
fontSize: 13,
},
stockControl: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#1c1c2e',
borderRadius: 12,
backgroundColor: colors.surfaceMuted,
borderRadius: radius.md,
padding: 4,
gap: 12,
marginRight: 10,
@@ -657,18 +667,20 @@ const styles = StyleSheet.create({
stockBtn: {
width: 28,
height: 28,
borderRadius: 8,
backgroundColor: '#252538',
borderRadius: radius.xs,
backgroundColor: colors.surface,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: colors.border,
},
stockBtnTxt: {
color: '#f8fafc',
color: colors.text,
fontSize: 16,
fontWeight: 'bold',
},
stockVal: {
color: '#f8fafc',
color: colors.text,
fontSize: 14,
fontWeight: '800',
minWidth: 20,
@@ -677,47 +689,47 @@ const styles = StyleSheet.create({
deleteIcon: {
width: 32,
height: 32,
borderRadius: 10,
backgroundColor: 'rgba(239,68,68,0.1)',
borderRadius: radius.md,
backgroundColor: colors.dangerSoft,
alignItems: 'center',
justifyContent: 'center',
},
deleteTxt: {
color: '#ef4444',
color: colors.danger,
fontSize: 12,
fontWeight: '900',
},
formCard: {
padding: 20,
gap: 12,
borderWidth: 1.5,
borderColor: 'rgba(99,102,241,0.2)',
borderRadius: 20,
borderWidth: 1,
borderColor: colors.borderStrong,
borderRadius: radius.sm,
marginTop: 10,
},
formTitle: {
color: '#f8fafc',
color: colors.text,
fontSize: 16,
fontWeight: '800',
marginBottom: 4,
},
input: {
backgroundColor: '#1c1c2e',
borderRadius: 12,
backgroundColor: colors.surfaceMuted,
borderRadius: radius.md,
paddingHorizontal: 14,
paddingVertical: 12,
color: '#f8fafc',
color: colors.text,
fontSize: 14,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.04)',
borderColor: colors.border,
marginBottom: 8,
},
inputLabel: {
color: '#94a3b8',
color: colors.textMuted,
fontSize: 12,
fontWeight: '700',
textTransform: 'uppercase',
letterSpacing: 0.5,
letterSpacing: 0,
marginBottom: 8,
},
row: {
@@ -727,27 +739,28 @@ const styles = StyleSheet.create({
barberAvatar: {
width: 48,
height: 48,
borderRadius: 14,
backgroundColor: '#1c1c2e',
borderRadius: radius.md,
backgroundColor: colors.primarySoft,
alignItems: 'center',
justifyContent: 'center',
overflow: 'hidden',
},
avatarTxt: {
color: '#6366f1',
color: colors.primary,
fontSize: 20,
fontWeight: '900',
},
coverUpload: {
height: 180,
borderRadius: 22,
backgroundColor: '#141420',
borderRadius: radius.sm,
backgroundColor: colors.surface,
overflow: 'hidden',
position: 'relative',
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.06)',
borderColor: colors.border,
...shadows.card,
},
fullImg: {
width: '100%',
@@ -760,7 +773,7 @@ const styles = StyleSheet.create({
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: '#6366f1',
backgroundColor: colors.primary,
alignItems: 'center',
justifyContent: 'center',
elevation: 4,
@@ -769,7 +782,7 @@ const styles = StyleSheet.create({
fontSize: 18,
},
uploadTxt: {
color: '#475569',
color: colors.textMuted,
fontSize: 14,
fontWeight: '700',
},
@@ -780,7 +793,7 @@ const styles = StyleSheet.create({
marginBottom: 10,
},
dayLabel: {
color: '#f8fafc',
color: colors.text,
fontSize: 13,
fontWeight: '700',
width: 65,
@@ -788,22 +801,22 @@ const styles = StyleSheet.create({
closedBtn: {
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 6,
backgroundColor: 'rgba(16,185,129,0.1)',
borderRadius: radius.xs,
backgroundColor: colors.successSoft,
borderWidth: 1,
borderColor: 'rgba(16,185,129,0.2)',
borderColor: '#bbf7d0',
},
closedBtnActive: {
backgroundColor: 'rgba(239,68,68,0.1)',
borderColor: 'rgba(239,68,68,0.2)',
backgroundColor: colors.dangerSoft,
borderColor: '#fecaca',
},
closedText: {
color: '#10b981',
color: '#166534',
fontSize: 11,
fontWeight: '800',
},
closedTextActive: {
color: '#ef4444',
color: colors.danger,
},
timeInputs: {
flexDirection: 'row',
@@ -811,14 +824,14 @@ const styles = StyleSheet.create({
gap: 6,
},
timeInput: {
backgroundColor: '#1c1c2e',
borderRadius: 8,
backgroundColor: colors.surfaceMuted,
borderRadius: radius.xs,
paddingHorizontal: 8,
paddingVertical: 4,
color: '#f8fafc',
color: colors.text,
fontSize: 12,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.04)',
borderColor: colors.border,
width: 55,
textAlign: 'center',
},
@@ -826,33 +839,33 @@ const styles = StyleSheet.create({
marginTop: 40,
paddingTop: 20,
borderTopWidth: 1,
borderTopColor: 'rgba(255,255,255,0.06)',
borderTopColor: colors.border,
alignItems: 'center',
},
logoutButtonPremium: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(239,68,68,0.1)',
backgroundColor: colors.dangerSoft,
paddingVertical: 16,
paddingHorizontal: 24,
borderRadius: 16,
borderRadius: radius.sm,
width: '100%',
borderWidth: 1,
borderColor: 'rgba(239,68,68,0.2)',
borderColor: '#fecaca',
gap: 12,
},
logoutButtonText: {
color: '#ef4444',
color: colors.danger,
fontSize: 16,
fontWeight: '800',
},
logoutButtonIcon: {
color: '#ef4444',
color: colors.danger,
fontSize: 20,
},
versionText: {
color: '#334155',
color: colors.textSubtle,
fontSize: 12,
marginTop: 16,
fontWeight: '600',

View File

@@ -8,6 +8,7 @@ import { Input } from '../components/ui/Input';
import { Button } from '../components/ui/Button';
import { createEvent } from '../lib/events';
import { RootStackParamList } from '../navigation/types';
import { colors, radius, shadows } from '../lib/theme';
export default function EventsCreate() {
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
@@ -100,7 +101,7 @@ export default function EventsCreate() {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f8fafc',
backgroundColor: colors.background,
},
content: {
padding: 16,
@@ -109,19 +110,21 @@ const styles = StyleSheet.create({
},
card: {
padding: 24,
borderRadius: radius.sm,
},
iconBox: {
width: 56,
height: 56,
borderRadius: 16,
backgroundColor: '#0f172a',
borderRadius: radius.md,
backgroundColor: colors.surfaceDark,
alignItems: 'center',
justifyContent: 'center',
alignSelf: 'center',
marginBottom: 16,
...shadows.soft,
},
iconText: {
color: '#818cf8',
color: colors.accentSoft,
fontSize: 32,
fontWeight: '900',
lineHeight: 36,
@@ -129,22 +132,22 @@ const styles = StyleSheet.create({
title: {
fontSize: 28,
fontWeight: '900',
color: '#0f172a',
color: colors.text,
textAlign: 'center',
},
subtitle: {
fontSize: 14,
color: '#64748b',
color: colors.textMuted,
textAlign: 'center',
marginTop: 6,
marginBottom: 24,
},
error: {
backgroundColor: '#fff1f2',
borderColor: '#fecdd3',
backgroundColor: colors.dangerSoft,
borderColor: '#fecaca',
borderWidth: 1,
borderRadius: 14,
color: '#be123c',
borderRadius: radius.md,
color: '#991b1b',
padding: 12,
marginBottom: 16,
fontWeight: '600',

View File

@@ -7,6 +7,7 @@ import { useApp } from '../context/AppContext';
import { Card } from '../components/ui/Card';
import { Button } from '../components/ui/Button';
import { RootStackParamList } from '../navigation/types';
import { colors, radius, shadows } from '../lib/theme';
export default function Explore() {
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
@@ -31,29 +32,31 @@ export default function Explore() {
return (
<SafeAreaView style={styles.container}>
<ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled">
{/* Header */}
<View style={styles.header}>
<View>
<Text style={styles.greeting}>
{user ? `Olá, ${user.name.split(' ')[0]}` : 'Descobre'}
</Text>
<Text style={styles.headline}>Barbearias</Text>
<View style={styles.heroPanel}>
{/* Header */}
<View style={styles.header}>
<View>
<Text style={styles.greeting}>
{user ? `Olá, ${user.name.split(' ')[0]}` : 'Descobre'}
</Text>
<Text style={styles.headline}>Barbearias</Text>
</View>
<View style={styles.brandPill}>
<Text style={styles.brandText}>SA</Text>
</View>
</View>
<View style={styles.brandPill}>
<Text style={styles.brandText}>SA</Text>
</View>
</View>
{/* Search */}
<View style={styles.searchBox}>
<Text style={styles.searchIcon}></Text>
<TextInput
value={query}
onChangeText={setQuery}
placeholder="Pesquisar nome ou endereço..."
placeholderTextColor="#475569"
style={styles.searchInput}
/>
{/* Search */}
<View style={styles.searchBox}>
<Text style={styles.searchIcon}></Text>
<TextInput
value={query}
onChangeText={setQuery}
placeholder="Pesquisar nome ou endereço..."
placeholderTextColor={colors.placeholder}
style={styles.searchInput}
/>
</View>
</View>
{/* Filters */}
@@ -135,62 +138,69 @@ export default function Explore() {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0a0a0f',
backgroundColor: colors.background,
},
content: {
padding: 20,
gap: 20,
gap: 18,
paddingBottom: 32,
},
heroPanel: {
backgroundColor: colors.surfaceDark,
borderRadius: radius.sm,
padding: 18,
gap: 18,
...shadows.card,
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-start',
},
greeting: {
color: '#64748b',
color: '#b7c4bf',
fontSize: 15,
fontWeight: '600',
marginBottom: 2,
},
headline: {
color: '#f8fafc',
color: colors.textInverse,
fontSize: 32,
fontWeight: '900',
},
brandPill: {
width: 44,
height: 44,
borderRadius: 14,
backgroundColor: '#141420',
borderRadius: radius.md,
backgroundColor: colors.accentSoft,
borderWidth: 1,
borderColor: 'rgba(99,102,241,0.25)',
borderColor: 'rgba(255,255,255,0.18)',
alignItems: 'center',
justifyContent: 'center',
},
brandText: {
color: '#818cf8',
color: '#7a4310',
fontSize: 14,
fontWeight: '900',
},
searchBox: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#141420',
borderRadius: 16,
backgroundColor: colors.surface,
borderRadius: radius.md,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.06)',
borderColor: 'rgba(255,255,255,0.14)',
paddingHorizontal: 16,
gap: 10,
},
searchIcon: {
color: '#475569',
color: colors.primary,
fontSize: 20,
},
searchInput: {
flex: 1,
height: 52,
color: '#f8fafc',
color: colors.text,
fontSize: 15,
fontWeight: '500',
},
@@ -198,41 +208,42 @@ const styles = StyleSheet.create({
gap: 8,
},
chip: {
borderRadius: 12,
backgroundColor: '#141420',
borderRadius: radius.pill,
backgroundColor: colors.surface,
paddingHorizontal: 16,
paddingVertical: 10,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.04)',
borderColor: colors.border,
},
chipActive: {
backgroundColor: '#6366f1',
borderColor: '#6366f1',
backgroundColor: colors.primary,
borderColor: colors.primary,
},
chipText: {
color: '#94a3b8',
color: colors.textMuted,
fontSize: 13,
fontWeight: '700',
},
chipTextActive: {
color: '#fff',
color: colors.textInverse,
},
list: {
gap: 16,
},
count: {
color: '#475569',
color: colors.textMuted,
fontSize: 12,
fontWeight: '700',
textTransform: 'uppercase',
letterSpacing: 0.5,
letterSpacing: 0,
},
shopCard: {
borderRadius: 22,
borderRadius: radius.sm,
overflow: 'hidden',
backgroundColor: '#141420',
backgroundColor: colors.surface,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.04)',
borderColor: colors.border,
...shadows.card,
},
shopImage: {
width: '100%',
@@ -241,12 +252,12 @@ const styles = StyleSheet.create({
shopImageFallback: {
width: '100%',
height: 160,
backgroundColor: '#1c1c2e',
backgroundColor: colors.primarySoft,
alignItems: 'center',
justifyContent: 'center',
},
shopFallbackText: {
color: '#6366f1',
color: colors.primary,
fontSize: 42,
fontWeight: '900',
opacity: 0.5,
@@ -266,21 +277,21 @@ const styles = StyleSheet.create({
flex: 1,
fontSize: 18,
fontWeight: '800',
color: '#f8fafc',
color: colors.text,
},
ratingPill: {
backgroundColor: 'rgba(99,102,241,0.15)',
borderRadius: 10,
backgroundColor: colors.accentSoft,
borderRadius: radius.pill,
paddingHorizontal: 10,
paddingVertical: 5,
},
ratingText: {
color: '#a5b4fc',
color: '#7a4310',
fontSize: 12,
fontWeight: '800',
},
address: {
color: '#64748b',
color: colors.textMuted,
fontWeight: '500',
fontSize: 14,
},
@@ -289,13 +300,13 @@ const styles = StyleSheet.create({
gap: 8,
},
metaPill: {
backgroundColor: 'rgba(255,255,255,0.04)',
borderRadius: 8,
backgroundColor: colors.surfaceMuted,
borderRadius: radius.xs,
paddingHorizontal: 10,
paddingVertical: 5,
},
metaText: {
color: '#475569',
color: colors.textMuted,
fontSize: 11,
fontWeight: '700',
textTransform: 'uppercase',
@@ -310,13 +321,13 @@ const styles = StyleSheet.create({
marginBottom: 8,
},
emptyTitle: {
color: '#f8fafc',
color: colors.text,
fontSize: 18,
fontWeight: '800',
textAlign: 'center',
},
emptyText: {
color: '#64748b',
color: colors.textMuted,
textAlign: 'center',
fontWeight: '500',
},

View File

@@ -7,6 +7,7 @@ import { Button } from '../components/ui/Button';
import { Card } from '../components/ui/Card';
import { useApp } from '../context/AppContext';
import { RootStackParamList } from '../navigation/types';
import { colors, radius, shadows } from '../lib/theme';
export default function Landing() {
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
@@ -118,30 +119,31 @@ export default function Landing() {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f8fafc',
backgroundColor: colors.background,
},
content: {
padding: 16,
gap: 22,
},
hero: {
backgroundColor: '#020617',
borderRadius: 28,
backgroundColor: colors.surfaceDark,
borderRadius: radius.sm,
padding: 24,
overflow: 'hidden',
...shadows.card,
},
kicker: {
alignSelf: 'flex-start',
backgroundColor: 'rgba(99,102,241,0.16)',
borderColor: 'rgba(129,140,248,0.35)',
backgroundColor: colors.primarySoft,
borderColor: 'rgba(255,255,255,0.18)',
borderWidth: 1,
borderRadius: 999,
borderRadius: radius.pill,
paddingHorizontal: 12,
paddingVertical: 7,
marginBottom: 22,
},
kickerText: {
color: '#a5b4fc',
color: colors.primaryDark,
fontSize: 10,
fontWeight: '900',
textTransform: 'uppercase',
@@ -155,10 +157,10 @@ const styles = StyleSheet.create({
textTransform: 'uppercase',
},
heroAccent: {
color: '#818cf8',
color: colors.accentSoft,
},
heroDesc: {
color: '#cbd5e1',
color: '#dce7e1',
fontSize: 17,
lineHeight: 24,
fontWeight: '500',
@@ -175,7 +177,7 @@ const styles = StyleSheet.create({
color: '#0f172a',
},
secondaryHeroButton: {
borderColor: 'rgba(255,255,255,0.24)',
borderColor: 'rgba(255,255,255,0.28)',
backgroundColor: 'transparent',
},
secondaryHeroText: {
@@ -198,10 +200,10 @@ const styles = StyleSheet.create({
fontWeight: '900',
},
statAccent: {
color: '#818cf8',
color: colors.accentSoft,
},
statLabel: {
color: '#94a3b8',
color: '#b7c4bf',
fontSize: 9,
fontWeight: '900',
textTransform: 'uppercase',
@@ -211,14 +213,14 @@ const styles = StyleSheet.create({
gap: 6,
},
sectionTitle: {
color: '#0f172a',
color: colors.text,
fontSize: 30,
lineHeight: 32,
fontWeight: '900',
textTransform: 'uppercase',
},
sectionSubtitle: {
color: '#64748b',
color: colors.textMuted,
fontSize: 15,
lineHeight: 22,
fontWeight: '500',
@@ -232,26 +234,26 @@ const styles = StyleSheet.create({
featureIcon: {
width: 56,
height: 56,
borderRadius: 16,
backgroundColor: '#eef2ff',
borderRadius: radius.md,
backgroundColor: colors.primarySoft,
alignItems: 'center',
justifyContent: 'center',
marginBottom: 14,
},
featureIconText: {
color: '#4f46e5',
color: colors.primary,
fontWeight: '900',
fontSize: 22,
},
featureTitle: {
color: '#0f172a',
color: colors.text,
fontSize: 20,
fontWeight: '900',
textTransform: 'uppercase',
marginBottom: 8,
},
featureDesc: {
color: '#64748b',
color: colors.textMuted,
fontSize: 14,
lineHeight: 20,
fontWeight: '500',
@@ -267,12 +269,12 @@ const styles = StyleSheet.create({
},
shopImageFallback: {
height: 150,
backgroundColor: '#0f172a',
backgroundColor: colors.primarySoft,
alignItems: 'center',
justifyContent: 'center',
},
shopImageFallbackText: {
color: '#818cf8',
color: colors.primary,
fontWeight: '900',
fontSize: 24,
},
@@ -287,30 +289,30 @@ const styles = StyleSheet.create({
},
shopName: {
flex: 1,
color: '#0f172a',
color: colors.text,
fontSize: 20,
fontWeight: '900',
},
rating: {
color: '#fff',
backgroundColor: '#0f172a',
borderRadius: 999,
color: '#7a4310',
backgroundColor: colors.accentSoft,
borderRadius: radius.pill,
paddingHorizontal: 10,
paddingVertical: 4,
fontSize: 12,
fontWeight: '900',
},
shopAddress: {
color: '#64748b',
color: colors.textMuted,
fontWeight: '500',
},
darkButton: {
backgroundColor: '#0f172a',
backgroundColor: colors.surfaceDark,
marginTop: 6,
},
finalCta: {
backgroundColor: '#020617',
borderRadius: 28,
backgroundColor: colors.surfaceDark,
borderRadius: radius.sm,
padding: 24,
gap: 14,
marginBottom: 16,
@@ -322,7 +324,7 @@ const styles = StyleSheet.create({
textTransform: 'uppercase',
},
finalText: {
color: '#cbd5e1',
color: '#dce7e1',
fontSize: 15,
lineHeight: 22,
fontWeight: '500',

View File

@@ -9,12 +9,13 @@ import { Button } from '../components/ui/Button';
import { currency } from '../lib/format';
import { RootStackParamList } from '../navigation/types';
import { supabase } from '../lib/supabase';
import { colors, radius, shadows } from '../lib/theme';
const statusColor: Record<string, string> = {
pendente: '#6366f1',
confirmado: '#10b981',
concluido: '#10b981',
cancelado: '#ef4444',
pendente: colors.primary,
confirmado: colors.success,
concluido: colors.success,
cancelado: colors.danger,
};
const statusLabel: Record<string, string> = {
@@ -284,7 +285,7 @@ export default function Profile() {
</TouchableOpacity>
))}
</View>
<TextInput style={styles.reviewInput} placeholder="Diz-nos o que achaste..." placeholderTextColor="#475569" multiline value={comment} onChangeText={setComment} />
<TextInput style={styles.reviewInput} placeholder="Diz-nos o que achaste..." placeholderTextColor={colors.placeholder} multiline value={comment} onChangeText={setComment} />
<View style={styles.reviewActions}>
<Button variant="ghost" onPress={() => setReviewTarget(null)} style={{ flex: 1 }}>Cancelar</Button>
<Button onPress={handleReviewSubmit} loading={submittingReview} disabled={rating === 0} style={{ flex: 2 }}>Enviar</Button>
@@ -305,96 +306,96 @@ export default function Profile() {
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#0a0a0f' },
container: { flex: 1, backgroundColor: colors.background },
content: { padding: 20, paddingBottom: 100 },
profileHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 32, gap: 16 },
avatarBox: { width: 64, height: 64, borderRadius: 22, backgroundColor: '#141420', alignItems: 'center', justifyContent: 'center', borderWidth: 1, borderColor: 'rgba(99,102,241,0.3)' },
avatarText: { color: '#818cf8', fontSize: 24, fontWeight: '900' },
profileHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 28, gap: 16, backgroundColor: colors.surfaceDark, borderRadius: radius.sm, padding: 18, ...shadows.card },
avatarBox: { width: 64, height: 64, borderRadius: radius.lg, backgroundColor: colors.accentSoft, alignItems: 'center', justifyContent: 'center', borderWidth: 1, borderColor: 'rgba(255,255,255,0.16)' },
avatarText: { color: '#7a4310', fontSize: 24, fontWeight: '900' },
profileInfo: { flex: 1, gap: 2 },
profileName: { color: '#f8fafc', fontSize: 22, fontWeight: '900' },
profileEmail: { color: '#64748b', fontSize: 14, fontWeight: '500' },
roleBadge: { alignSelf: 'flex-start', backgroundColor: 'rgba(99,102,241,0.1)', borderRadius: 8, paddingHorizontal: 8, paddingVertical: 3, marginTop: 4 },
roleText: { color: '#818cf8', fontSize: 10, fontWeight: '800', textTransform: 'uppercase' },
profileName: { color: colors.textInverse, fontSize: 22, fontWeight: '900' },
profileEmail: { color: '#b7c4bf', fontSize: 14, fontWeight: '500' },
roleBadge: { alignSelf: 'flex-start', backgroundColor: colors.primarySoft, borderRadius: radius.pill, paddingHorizontal: 10, paddingVertical: 4, marginTop: 6 },
roleText: { color: colors.primaryDark, fontSize: 10, fontWeight: '800', textTransform: 'uppercase' },
reviewActions: { flexDirection: 'row', gap: 14 },
sectionTitle: { color: '#f8fafc', fontSize: 18, fontWeight: '800', marginBottom: 12 },
sectionTitle: { color: colors.text, fontSize: 18, fontWeight: '800', marginBottom: 12 },
notifSection: { marginBottom: 32 },
notifScroll: { marginHorizontal: -20, paddingHorizontal: 20 },
notifCard: { backgroundColor: '#141420', width: 240, borderRadius: 20, padding: 16, marginRight: 12, borderWidth: 1, borderColor: 'rgba(255,255,255,0.06)', gap: 8, elevation: 2 },
notifUnread: { borderColor: 'rgba(99,102,241,0.3)', backgroundColor: '#18182b' },
notifMsg: { color: '#94a3b8', fontSize: 13, lineHeight: 18, fontWeight: '500' },
markRead: { color: '#818cf8', fontSize: 12, fontWeight: '800', textTransform: 'uppercase', letterSpacing: 0.5 },
tabBar: { flexDirection: 'row', marginBottom: 24, borderBottomWidth: 1, borderBottomColor: 'rgba(255,255,255,0.06)' },
notifCard: { backgroundColor: colors.surface, width: 240, borderRadius: radius.sm, padding: 16, marginRight: 12, borderWidth: 1, borderColor: colors.border, gap: 8, ...shadows.soft },
notifUnread: { borderColor: colors.primary, backgroundColor: colors.primarySoft },
notifMsg: { color: colors.textMuted, fontSize: 13, lineHeight: 18, fontWeight: '500' },
markRead: { color: colors.primaryDark, fontSize: 12, fontWeight: '800', textTransform: 'uppercase', letterSpacing: 0 },
tabBar: { flexDirection: 'row', marginBottom: 24, borderBottomWidth: 1, borderBottomColor: colors.border },
tabItem: { paddingVertical: 14, marginRight: 24, position: 'relative' },
tabActive: {},
tabText: { color: '#64748b', fontSize: 15, fontWeight: '700' },
tabTextActive: { color: '#f8fafc' },
tabIndicator: { position: 'absolute', bottom: -1, left: 0, right: 0, height: 3, backgroundColor: '#6366f1', borderRadius: 4 },
tabText: { color: colors.textMuted, fontSize: 15, fontWeight: '700' },
tabTextActive: { color: colors.text },
tabIndicator: { position: 'absolute', bottom: -1, left: 0, right: 0, height: 3, backgroundColor: colors.primary, borderRadius: radius.pill },
tabContent: { minHeight: 200 },
listContainer: { gap: 16 },
emptyTxt: { color: '#64748b', textAlign: 'center', marginTop: 20, fontWeight: '600' },
subTitle: { color: '#64748b', fontSize: 13, fontWeight: '700', textTransform: 'uppercase', marginBottom: 8, letterSpacing: 1 },
agendaCard: { padding: 16, gap: 12, backgroundColor: '#141420', borderRadius: 20, borderWidth: 1, borderColor: 'rgba(255,255,255,0.03)' },
emptyTxt: { color: colors.textMuted, textAlign: 'center', marginTop: 20, fontWeight: '600' },
subTitle: { color: colors.textMuted, fontSize: 13, fontWeight: '700', textTransform: 'uppercase', marginBottom: 8, letterSpacing: 0 },
agendaCard: { padding: 16, gap: 12, backgroundColor: colors.surface, borderRadius: radius.sm, borderWidth: 1, borderColor: colors.border },
agendaTop: { flexDirection: 'row', alignItems: 'center', gap: 14 },
dateBox: { backgroundColor: '#1c1c2e', padding: 10, borderRadius: 14, alignItems: 'center', minWidth: 55, borderWidth: 1, borderColor: 'rgba(255,255,255,0.05)' },
dateDay: { color: '#f8fafc', fontSize: 20, fontWeight: '900' },
dateMonth: { color: '#818cf8', fontSize: 10, fontWeight: '800', textTransform: 'uppercase' },
dateBox: { backgroundColor: colors.primarySoft, padding: 10, borderRadius: radius.md, alignItems: 'center', minWidth: 55, borderWidth: 1, borderColor: colors.border },
dateDay: { color: colors.primaryDark, fontSize: 20, fontWeight: '900' },
dateMonth: { color: colors.primary, fontSize: 10, fontWeight: '800', textTransform: 'uppercase' },
agendaMain: { flex: 1, gap: 3 },
agendaShop: { color: '#f8fafc', fontSize: 17, fontWeight: '800' },
agendaTime: { color: '#64748b', fontSize: 13, fontWeight: '500' },
statusTag: { paddingHorizontal: 12, paddingVertical: 6, borderRadius: 10 },
statusText: { fontSize: 10, fontWeight: '900', textTransform: 'uppercase', letterSpacing: 0.5 },
reviewBtn: { marginTop: 8, borderRadius: 12 },
shopCard: { flexDirection: 'row', alignItems: 'center', gap: 14, padding: 16, backgroundColor: '#141420', borderRadius: 20, marginBottom: 4 },
shopIcon: { width: 48, height: 48, borderRadius: 14, backgroundColor: 'rgba(99,102,241,0.05)', alignItems: 'center', justifyContent: 'center', borderWidth: 1, borderColor: 'rgba(99,102,241,0.1)' },
shopIconText: { color: '#818cf8', fontSize: 20, fontWeight: '900' },
shopName: { color: '#f8fafc', fontSize: 16, fontWeight: '800' },
shopAddr: { color: '#475569', fontSize: 12, fontWeight: '500' },
shopRating: { color: '#fbbf24', fontWeight: '900', fontSize: 14 },
reviewCard: { padding: 18, gap: 10, backgroundColor: '#141420', borderRadius: 20 },
agendaShop: { color: colors.text, fontSize: 17, fontWeight: '800' },
agendaTime: { color: colors.textMuted, fontSize: 13, fontWeight: '500' },
statusTag: { paddingHorizontal: 12, paddingVertical: 6, borderRadius: radius.pill },
statusText: { fontSize: 10, fontWeight: '900', textTransform: 'uppercase', letterSpacing: 0 },
reviewBtn: { marginTop: 8, borderRadius: radius.md },
shopCard: { flexDirection: 'row', alignItems: 'center', gap: 14, padding: 16, backgroundColor: colors.surface, borderRadius: radius.sm, marginBottom: 4 },
shopIcon: { width: 48, height: 48, borderRadius: radius.md, backgroundColor: colors.primarySoft, alignItems: 'center', justifyContent: 'center', borderWidth: 1, borderColor: colors.border },
shopIconText: { color: colors.primary, fontSize: 20, fontWeight: '900' },
shopName: { color: colors.text, fontSize: 16, fontWeight: '800' },
shopAddr: { color: colors.textMuted, fontSize: 12, fontWeight: '500' },
shopRating: { color: colors.star, fontWeight: '900', fontSize: 14 },
reviewCard: { padding: 18, gap: 10, backgroundColor: colors.surface, borderRadius: radius.sm },
reviewHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },
reviewStars: { color: '#fbbf24', fontSize: 15 },
reviewDate: { color: '#475569', fontSize: 12, fontWeight: '600' },
reviewComment: { color: '#f8fafc', fontSize: 14, lineHeight: 20, fontWeight: '400' },
statCard: { padding: 24, alignItems: 'center', gap: 6, backgroundColor: '#141420', borderRadius: 24, borderWidth: 1, borderColor: 'rgba(99,102,241,0.1)' },
statLabel: { color: '#64748b', fontSize: 12, fontWeight: '700', textTransform: 'uppercase', letterSpacing: 1 },
statValue: { color: '#f8fafc', fontSize: 28, fontWeight: '900' },
reviewModal: { marginTop: 24, padding: 24, gap: 16, borderColor: 'rgba(99,102,241,0.3)', borderRadius: 24 },
reviewTitle: { color: '#f8fafc', fontSize: 18, fontWeight: '800', textAlign: 'center' },
reviewStars: { color: colors.star, fontSize: 15 },
reviewDate: { color: colors.textSubtle, fontSize: 12, fontWeight: '600' },
reviewComment: { color: colors.text, fontSize: 14, lineHeight: 20, fontWeight: '400' },
statCard: { padding: 24, alignItems: 'center', gap: 6, backgroundColor: colors.surface, borderRadius: radius.sm, borderWidth: 1, borderColor: colors.border },
statLabel: { color: colors.textMuted, fontSize: 12, fontWeight: '700', textTransform: 'uppercase', letterSpacing: 0 },
statValue: { color: colors.text, fontSize: 28, fontWeight: '900' },
reviewModal: { marginTop: 24, padding: 24, gap: 16, borderColor: colors.primary, borderRadius: radius.sm },
reviewTitle: { color: colors.text, fontSize: 18, fontWeight: '800', textAlign: 'center' },
stars: { flexDirection: 'row', justifyContent: 'center', gap: 12 },
star: { fontSize: 36, color: '#1c1c2e' },
starActive: { color: '#fbbf24' },
reviewInput: { backgroundColor: '#1c1c2e', borderRadius: 16, padding: 16, color: '#f8fafc', height: 100, textAlignVertical: 'top', borderWidth: 1, borderColor: 'rgba(255,255,255,0.05)' },
star: { fontSize: 36, color: colors.borderStrong },
starActive: { color: colors.star },
reviewInput: { backgroundColor: colors.surfaceMuted, borderRadius: radius.md, padding: 16, color: colors.text, height: 100, textAlignVertical: 'top', borderWidth: 1, borderColor: colors.border },
logoutSection: {
marginTop: 60,
paddingTop: 30,
borderTopWidth: 1,
borderTopColor: 'rgba(255,255,255,0.06)',
borderTopColor: colors.border,
alignItems: 'center',
},
logoutButtonPremium: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(239,68,68,0.1)',
backgroundColor: colors.dangerSoft,
paddingVertical: 18,
paddingHorizontal: 24,
borderRadius: 20,
borderRadius: radius.sm,
width: '100%',
borderWidth: 1,
borderColor: 'rgba(239,68,68,0.2)',
borderColor: '#fecaca',
gap: 12,
},
logoutButtonText: {
color: '#ef4444',
color: colors.danger,
fontSize: 16,
fontWeight: '800',
},
logoutButtonIcon: {
color: '#ef4444',
color: colors.danger,
fontSize: 20,
},
versionText: {
color: '#334155',
color: colors.textSubtle,
fontSize: 12,
marginTop: 16,
fontWeight: '600',

View File

@@ -8,6 +8,7 @@ import { Card } from '../components/ui/Card';
import { Button } from '../components/ui/Button';
import { currency } from '../lib/format';
import { RootStackParamList } from '../navigation/types';
import { colors, radius } from '../lib/theme';
type Tab = 'servicos' | 'barbeiros' | 'produtos' | 'detalhes';
@@ -199,13 +200,13 @@ export default function ShopDetails() {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#0a0a0f',
backgroundColor: colors.background,
},
scrollContent: {
paddingBottom: 40,
},
hero: {
height: 380,
height: 360,
position: 'relative',
},
heroImage: {
@@ -215,7 +216,7 @@ const styles = StyleSheet.create({
heroPlaceholder: {
width: '100%',
height: '100%',
backgroundColor: '#141420',
backgroundColor: colors.primarySoft,
alignItems: 'center',
justifyContent: 'center',
},
@@ -224,7 +225,7 @@ const styles = StyleSheet.create({
},
heroOverlay: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(10,10,15,0.5)',
backgroundColor: colors.overlay,
},
heroHeader: {
position: 'absolute',
@@ -239,30 +240,34 @@ const styles = StyleSheet.create({
backBtn: {
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: 'rgba(255,255,255,0.1)',
borderRadius: radius.pill,
backgroundColor: 'rgba(20,33,29,0.72)',
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.16)',
},
backIcon: {
color: '#fff',
color: colors.textInverse,
fontSize: 20,
fontWeight: '700',
},
favBtn: {
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: 'rgba(255,255,255,0.1)',
borderRadius: radius.pill,
backgroundColor: 'rgba(20,33,29,0.72)',
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.16)',
},
favIcon: {
color: '#fff',
color: colors.textInverse,
fontSize: 22,
},
favActive: {
color: '#ef4444',
color: colors.danger,
},
heroBody: {
position: 'absolute',
@@ -273,18 +278,18 @@ const styles = StyleSheet.create({
},
ratingBox: {
alignSelf: 'flex-start',
backgroundColor: 'rgba(99,102,241,0.9)',
borderRadius: 8,
backgroundColor: colors.accent,
borderRadius: radius.pill,
paddingHorizontal: 10,
paddingVertical: 4,
},
ratingValue: {
color: '#fff',
color: colors.textInverse,
fontSize: 12,
fontWeight: '900',
},
shopName: {
color: '#fff',
color: colors.textInverse,
fontSize: 32,
fontWeight: '900',
},
@@ -292,34 +297,39 @@ const styles = StyleSheet.create({
opacity: 0.8,
},
shopAddr: {
color: '#f8fafc',
color: colors.textInverse,
fontSize: 14,
fontWeight: '500',
},
tabSection: {
backgroundColor: '#141420',
paddingVertical: 6,
backgroundColor: colors.surface,
paddingVertical: 10,
borderBottomWidth: 1,
borderBottomColor: colors.border,
},
tabsScroll: {
paddingHorizontal: 20,
gap: 16,
gap: 8,
},
tabItem: {
paddingVertical: 14,
paddingHorizontal: 4,
borderBottomWidth: 2,
borderBottomColor: 'transparent',
paddingVertical: 10,
paddingHorizontal: 14,
borderRadius: radius.pill,
backgroundColor: colors.surfaceMuted,
borderWidth: 1,
borderColor: colors.border,
},
tabItemActive: {
borderBottomColor: '#6366f1',
backgroundColor: colors.primary,
borderColor: colors.primary,
},
tabText: {
color: '#475569',
color: colors.textMuted,
fontSize: 14,
fontWeight: '700',
},
tabTextActive: {
color: '#f8fafc',
color: colors.textInverse,
},
contentArea: {
padding: 20,
@@ -338,12 +348,12 @@ const styles = StyleSheet.create({
gap: 4,
},
svcName: {
color: '#f8fafc',
color: colors.text,
fontSize: 16,
fontWeight: '800',
},
svcMeta: {
color: '#64748b',
color: colors.textMuted,
fontSize: 13,
},
barberList: {
@@ -358,23 +368,23 @@ const styles = StyleSheet.create({
barberAvatar: {
width: 50,
height: 50,
borderRadius: 16,
backgroundColor: '#1c1c2e',
borderRadius: radius.md,
backgroundColor: colors.primarySoft,
alignItems: 'center',
justifyContent: 'center',
},
avatarTxt: {
color: '#6366f1',
color: colors.primary,
fontSize: 20,
fontWeight: '900',
},
barberName: {
color: '#f8fafc',
color: colors.text,
fontSize: 16,
fontWeight: '800',
},
barberSpecs: {
color: '#475569',
color: colors.textMuted,
fontSize: 12,
},
productCard: {
@@ -387,18 +397,18 @@ const styles = StyleSheet.create({
alignItems: 'flex-start',
},
prodName: {
color: '#f8fafc',
color: colors.text,
fontSize: 16,
fontWeight: '800',
flex: 1,
},
prodPrice: {
color: '#a5b4fc',
color: colors.primary,
fontSize: 16,
fontWeight: '900',
},
prodStock: {
color: '#475569',
color: colors.textMuted,
fontSize: 12,
marginBottom: 4,
},
@@ -407,7 +417,7 @@ const styles = StyleSheet.create({
gap: 12,
},
detailTitle: {
color: '#f8fafc',
color: colors.text,
fontSize: 18,
fontWeight: '800',
marginBottom: 8,
@@ -417,25 +427,25 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
},
schedDay: {
color: '#64748b',
color: colors.textMuted,
fontSize: 14,
},
schedTime: {
color: '#f8fafc',
color: colors.text,
fontSize: 14,
fontWeight: '600',
},
today: {
color: '#6366f1',
color: colors.primary,
fontWeight: '800',
},
divider: {
height: 1,
backgroundColor: 'rgba(255,255,255,0.06)',
backgroundColor: colors.border,
marginVertical: 12,
},
contactLink: {
color: '#818cf8',
color: colors.primaryDark,
fontSize: 16,
fontWeight: '700',
},
@@ -446,7 +456,7 @@ const styles = StyleSheet.create({
padding: 40,
},
centerTitle: {
color: '#f8fafc',
color: colors.text,
fontSize: 18,
fontWeight: '800',
},