503 lines
12 KiB
TypeScript
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,
|
|
},
|
|
});
|