503 lines
12 KiB
TypeScript

import { StyleSheet, Dimensions, Platform } from 'react-native';
import { typography } from '@theme';
const { width, height } = Dimensions.get('window');
const HERO_HEIGHT = height * 0.45;
export const getStyles = (colors: any) =>
StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.background,
},
content: {
flex: 1,
},
contentBody: {
paddingBottom: 100, // Space for sticky bottom bar
},
// ---------- Image Carousel ----------
carouselWrap: {
width,
height: HERO_HEIGHT,
backgroundColor: colors.background,
},
carouselImage: {
width,
height: HERO_HEIGHT,
resizeMode: 'contain',
},
paginationDots: {
position: 'absolute',
bottom: 20,
alignSelf: 'center',
flexDirection: 'row',
backgroundColor: 'rgba(255,255,255,0.7)',
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 12,
},
dot: {
width: 6,
height: 6,
borderRadius: 3,
backgroundColor: colors.border,
marginHorizontal: 3,
},
dotActive: {
width: 14,
backgroundColor: colors.primary,
},
fallbackIconWrap: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: colors.surface,
},
fallbackIcon: {
fontSize: 60,
},
// Floating top icon row (back / share / favorite)
topIconRow: {
position: 'absolute',
top: Platform.OS === 'ios' ? 54 : 16,
left: 16,
right: 16,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
zIndex: 10,
},
iconButton: {
width: 42,
height: 42,
borderRadius: 21,
backgroundColor: 'rgba(255,255,255,0.95)',
alignItems: 'center',
justifyContent: 'center',
...Platform.select({
ios: {
shadowColor: '#000',
shadowOffset: { width: 0, height: 3 },
shadowOpacity: 0.15,
shadowRadius: 5,
},
android: { elevation: 4 },
}),
},
iconButtonText: {
fontSize: 18,
color: colors.text,
},
iconButtonGroup: {
flexDirection: 'row',
},
// ---------- Product Info Box ----------
infoBox: {
backgroundColor: colors.background,
marginTop: -20,
borderTopLeftRadius: 24,
borderTopRightRadius: 24,
paddingTop: 24,
paddingHorizontal: 20,
paddingBottom: 20,
...Platform.select({
ios: {
shadowColor: '#000',
shadowOffset: { width: 0, height: -4 },
shadowOpacity: 0.05,
shadowRadius: 8,
},
android: { elevation: 4 },
}),
},
brandRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 6,
},
brandText: {
fontSize: typography.fontSize.xs,
fontWeight: typography.fontWeight.bold,
color: colors.textSecondary,
textTransform: 'uppercase',
letterSpacing: 0.5,
},
ratingBadge: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: colors.primaryMuted ?? '#E9F7EF',
borderRadius: 6,
paddingHorizontal: 6,
paddingVertical: 3,
},
ratingBadgeText: {
fontSize: typography.fontSize.xs,
fontWeight: typography.fontWeight.bold,
color: colors.primary,
marginLeft: 4,
},
titleText: {
fontSize: 24,
fontWeight: typography.fontWeight.bold,
color: colors.text,
marginBottom: 12,
lineHeight: 32,
},
priceRow: {
flexDirection: 'row',
alignItems: 'flex-end',
marginBottom: 8,
},
priceText: {
fontSize: 28,
fontWeight: typography.fontWeight.bold,
color: colors.text,
marginRight: 10,
},
comparePriceText: {
fontSize: 16,
color: colors.textSecondary,
textDecorationLine: 'line-through',
marginBottom: 4,
},
discountBadgeWrap: {
marginLeft: 10,
marginBottom: 6,
backgroundColor: colors.error ?? '#E53935',
paddingHorizontal: 8,
paddingVertical: 3,
borderRadius: 6,
},
discountBadgeText: {
color: '#FFFFFF',
fontSize: typography.fontSize.xs,
fontWeight: typography.fontWeight.bold,
},
taxText: {
fontSize: typography.fontSize.sm,
color: colors.textSecondary,
},
// ---------- Section Divider ----------
sectionDivider: {
height: 8,
backgroundColor: colors.surface ?? '#F5F6F8',
},
// ---------- Details Section ----------
detailsSection: {
padding: 20,
backgroundColor: colors.background,
},
sectionTitle: {
fontSize: 18,
fontWeight: typography.fontWeight.bold,
color: colors.text,
marginBottom: 12,
},
descriptionText: {
fontSize: 15,
lineHeight: 24,
color: colors.textSecondary,
marginBottom: 20,
},
metaGrid: {
flexDirection: 'row',
flexWrap: 'wrap',
backgroundColor: colors.surface ?? '#F5F6F8',
borderRadius: 12,
padding: 16,
},
metaItem: {
width: '50%',
marginBottom: 12,
},
metaLabel: {
fontSize: 12,
color: colors.textSecondary,
marginBottom: 2,
},
metaValue: {
fontSize: 14,
fontWeight: typography.fontWeight.semibold,
color: colors.text,
},
// ---------- Sticky Bottom Bar ----------
bottomBarWrap: {
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
backgroundColor: colors.background,
paddingHorizontal: 20,
paddingTop: 16,
paddingBottom: Platform.OS === 'ios' ? 34 : 20,
borderTopWidth: 1,
borderTopColor: colors.border ?? '#ECECEC',
flexDirection: 'row',
alignItems: 'center',
},
qtySelector: {
flexDirection: 'row',
alignItems: 'center',
borderWidth: 1,
borderColor: colors.border,
borderRadius: 12,
marginRight: 16,
},
qtyBtn: {
width: 44,
height: 44,
alignItems: 'center',
justifyContent: 'center',
},
qtyBtnText: {
fontSize: 20,
color: colors.primary,
fontWeight: typography.fontWeight.medium,
},
qtyValue: {
fontSize: 16,
fontWeight: typography.fontWeight.bold,
color: colors.text,
width: 30,
textAlign: 'center',
},
addBtn: {
flex: 1,
backgroundColor: colors.primary,
height: 48,
borderRadius: 14,
alignItems: 'center',
justifyContent: 'center',
...Platform.select({
ios: {
shadowColor: colors.primary,
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.3,
shadowRadius: 8,
},
android: { elevation: 6 },
}),
},
addBtnText: {
fontSize: 16,
fontWeight: typography.fontWeight.bold,
color: '#FFFFFF',
},
// Skeleton loaders
skeletonTitle: {
width: '80%',
height: 32,
backgroundColor: colors.surface ?? '#EEEEEE',
borderRadius: 8,
marginBottom: 12,
},
skeletonPrice: {
width: '40%',
height: 28,
backgroundColor: colors.surface ?? '#EEEEEE',
borderRadius: 6,
marginBottom: 10,
},
skeletonText: {
width: '100%',
height: 16,
backgroundColor: colors.surface ?? '#EEEEEE',
borderRadius: 4,
marginBottom: 8,
},
// ================= Ratings & Reviews =================
ratingsSection: {
paddingHorizontal: 20,
paddingTop: 20,
paddingBottom: 24,
backgroundColor: colors.background,
},
ratingsHeaderRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 16,
},
seeAllText: {
fontSize: typography.fontSize.sm,
fontWeight: typography.fontWeight.semibold,
color: colors.primary,
},
// Summary card (big number + stars + optional breakdown bars)
ratingsSummaryCard: {
flexDirection: 'row',
backgroundColor: colors.surface ?? '#F5F6F8',
borderRadius: 16,
padding: 18,
marginBottom: 16,
...Platform.select({
ios: {
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.04,
shadowRadius: 6,
},
android: { elevation: 1 },
}),
},
ratingsSummaryLeft: {
alignItems: 'center',
justifyContent: 'center',
minWidth: 76,
},
ratingsSummaryLeftWithDivider: {
marginRight: 20,
paddingRight: 20,
borderRightWidth: StyleSheet.hairlineWidth,
borderRightColor: colors.border ?? '#E0E0E0',
},
avgRatingNumber: {
fontSize: 34,
fontWeight: typography.fontWeight.bold,
color: colors.text,
marginBottom: 4,
},
starsRow: {
flexDirection: 'row',
marginBottom: 6,
},
starIcon: {
marginRight: 1,
},
totalRatingsText: {
fontSize: typography.fontSize.xs,
color: colors.textSecondary,
},
ratingsBarsWrap: {
flex: 1,
justifyContent: 'center',
},
barRow: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 6,
},
barLabel: {
width: 26,
fontSize: typography.fontSize.xs,
color: colors.textSecondary,
textAlign: 'right',
marginRight: 8,
},
barTrack: {
flex: 1,
height: 6,
borderRadius: 3,
backgroundColor: colors.border ?? '#E5E5EA',
overflow: 'hidden',
},
barFill: {
height: '100%',
borderRadius: 3,
backgroundColor: colors.warning ?? '#F5A623',
},
// Empty state — styled as a card with a CTA, not bare text
emptyRatingsCard: {
backgroundColor: colors.surface ?? '#F5F6F8',
borderRadius: 16,
paddingVertical: 28,
paddingHorizontal: 20,
alignItems: 'center',
},
emptyRatingsIcon: {
fontSize: 30,
marginBottom: 10,
},
emptyRatingsTitle: {
fontSize: 15,
fontWeight: typography.fontWeight.semibold,
color: colors.text,
marginBottom: 4,
},
emptyRatingsSubtitle: {
fontSize: 13,
lineHeight: 18,
color: colors.textSecondary,
textAlign: 'center',
marginBottom: 16,
},
rateProductBtn: {
borderWidth: 1.5,
borderColor: colors.primary,
borderRadius: 10,
paddingVertical: 10,
paddingHorizontal: 24,
},
rateProductBtnText: {
fontSize: 14,
fontWeight: typography.fontWeight.semibold,
color: colors.primary,
},
// Recent reviews list
reviewsList: {
marginTop: 4,
},
reviewCard: {
backgroundColor: colors.background,
borderWidth: 1,
borderColor: colors.border ?? '#ECECEC',
borderRadius: 14,
padding: 14,
marginBottom: 12,
},
reviewCardHeader: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 10,
},
reviewerAvatar: {
width: 36,
height: 36,
borderRadius: 18,
backgroundColor: colors.primaryMuted ?? '#E9F7EF',
alignItems: 'center',
justifyContent: 'center',
marginRight: 10,
},
reviewerAvatarText: {
color: colors.primary,
fontSize: 15,
fontWeight: typography.fontWeight.bold,
},
reviewerName: {
fontSize: 13,
fontWeight: typography.fontWeight.semibold,
color: colors.text,
marginBottom: 3,
},
reviewDate: {
fontSize: 11,
color: colors.textSecondary,
},
reviewComment: {
fontSize: 13,
lineHeight: 19,
color: colors.textSecondary,
},
skeletonBlock: {
height: 90,
borderRadius: 16,
backgroundColor: colors.surface ?? '#EEEEEE',
marginBottom: 12,
},
});