Skip to content

Instantly share code, notes, and snippets.

@MDendiPurwanto
Last active June 8, 2025 15:03
Show Gist options
  • Save MDendiPurwanto/d6bfe23dd9ad3769e0b7956e4742b884 to your computer and use it in GitHub Desktop.
Save MDendiPurwanto/d6bfe23dd9ad3769e0b7956e4742b884 to your computer and use it in GitHub Desktop.
import React from 'react';
import {
SafeAreaView,
StatusBar,
StyleSheet,
Text,
View,
Image,
TextInput,
ScrollView,
TouchableOpacity,
Dimensions,
} from 'react-native';
// Definisi warna yang sering digunakan
const Colors = {
primaryRed: '#FF0000',
darkRed: '#9a0000',
white: '#FFFFFF',
lightGrey: '#F5F5F5',
greyText: '#666666',
darkGreyText: '#333333',
orangeCard: '#FFA500', // Warna mendekati oranye pada kartu Menu
pinkCard: '#FF69B4', // Warna mendekati pink pada kartu Reservasi
blueCard: '#4682B4', // Warna mendekati biru pada kartu Lokasi
maroonCard: '#800000', // Warna mendekati maroon pada kartu Jam Kerja
transparent: 'rgba(0,0,0,0)', // Transparan
};
/**
* Komponen MainScreen untuk AppsCigaleuh.
* Mengimplementasikan layout halaman utama sesuai desain Figma.
*/
const MainScreen = ({ navigation }) => { // Menerima prop navigation
// Komponen Card yang dapat digunakan kembali
// Menambahkan prop imageOnLeft untuk mengontrol posisi gambar
const MenuItemCard = ({ title, description, imageSource, cardColor, imageOnLeft = true, onPress }) => {
return (
<TouchableOpacity onPress={onPress} style={[
styles.cardContainer,
{ backgroundColor: cardColor },
{ flexDirection: imageOnLeft ? 'row' : 'row-reverse' }
]}>
{/* Gambar */}
<Image source={imageSource} style={styles.cardImage} />
{/* Konten teks */}
<View style={[
styles.cardContent,
{ marginLeft: imageOnLeft ? 15 : 0, marginRight: imageOnLeft ? 0 : 15 }
]}>
<Text style={styles.cardTitle}>{title}</Text>
<Text style={styles.cardDescription}>{description}</Text>
</View>
</TouchableOpacity>
);
};
return (
<SafeAreaView style={styles.container}>
{/* StatusBar untuk tampilan bar status */}
<StatusBar barStyle="dark-content" backgroundColor={Colors.white} />
{/* Header Section */}
<View style={styles.header}>
{/* Logo (Icon mangkuk) - Sekarang menggunakan Image lokal */}
<View style={styles.headerIconContainer}>
<Image
source={require('../assets/images/logo_header.png')}
style={styles.headerLogoImage}
onError={(e) => console.log('Gagal memuat logo header:', e.nativeEvent.error)}
/>
</View>
{/* Teks Header */}
<View style={styles.headerTextContainer}>
<Text style={styles.headerSanguAkeul}>SAUNG AKEUL</Text>
<Text style={styles.headerCigaleuh}>CIGALEUH</Text>
</View>
</View>
{/* Search Bar Section */}
<View style={styles.searchBarContainer}>
<TextInput
style={styles.searchInput}
placeholder="yuk cari di sini aja"
placeholderTextColor={Colors.greyText}
/>
<Image
source={require('../assets/images/search_icon.png')}
style={styles.searchIconImage}
onError={(e) => console.log('Gagal memuat ikon search:', e.nativeEvent.error)}
/>
</View>
{/* Content Area with ScrollView */}
<ScrollView contentContainerStyle={styles.contentScrollViewContent}>
{/* Menu Cards */}
<MenuItemCard
title="Menu"
description="Aneka makanan tradisional khususnya khas daerah Majalengka jawa barat"
imageSource={require('../assets/images/menu.png')}
cardColor={Colors.orangeCard}
imageOnLeft={true}
onPress={() => navigation.navigate('Menu')} // Menambahkan onPress untuk navigasi
/>
<MenuItemCard
title="Reservasi"
description="Reservasi terlebih dahulu agar saat datang sudah tinggal menikmati hidangan"
imageSource={require('../assets/images/reservasi.png')}
cardColor={Colors.pinkCard}
imageOnLeft={false}
onPress={() => console.log('Navigasi ke Reservasi')} // Contoh: navigasi ke layar Reservasi
/>
<MenuItemCard
title="Lokasi"
description="Jl. Joktrakad. Sani No.05, RT 03/RW 05, Majalengka Wetan, Kec. Majalengka, kabupaten \n Majalengka, Jawa Barat 45411"
imageSource={require('../assets/images/lokasi.png')}
cardColor={Colors.blueCard}
imageOnLeft={true}
onPress={() => console.log('Navigasi ke Lokasi')} // Contoh: navigasi ke layar Lokasi
/>
<MenuItemCard
title="Jam Kerja"
description="Senin - Jumat, 10:00 - 21:00\nSabtu - Minggu: 12:00 - 22:00"
imageSource={require('../assets/images/jam.png')}
cardColor={Colors.maroonCard}
imageOnLeft={false}
onPress={() => console.log('Navigasi ke Jam Kerja')} // Contoh: navigasi ke layar Jam Kerja
/>
<View style={{ height: 20 }} />
</ScrollView>
{/* Bottom Navigation */}
<View style={styles.bottomNav}>
<TouchableOpacity style={styles.navItem} onPress={() => navigation.navigate('Home')}>
<Image
source={require('../assets/images/nav_home_icon.png')}
style={styles.navImage}
onError={(e) => console.log('Gagal memuat ikon nav_home:', e.nativeEvent.error)}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.navItem} onPress={() => console.log('Navigasi ke FAQ')}>
<Image
source={require('../assets/images/nav_faq_icon.png')}
style={styles.navImage}
onError={(e) => console.log('Gagal memuat ikon nav_faq:', e.nativeEvent.error)}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.navItem} onPress={() => console.log('Navigasi ke Phone')}>
<Image
source={require('../assets/images/nav_phone_icon.png')}
style={styles.navImage}
onError={(e) => console.log('Gagal memuat ikon nav_phone:', e.nativeEvent.error)}
/>
</TouchableOpacity>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.lightGrey,
},
header: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 20,
paddingVertical: 15,
backgroundColor: Colors.white,
borderBottomWidth: 1,
borderBottomColor: '#EEE',
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 1.5,
},
headerIconContainer: {
marginRight: 10,
backgroundColor: Colors.primaryRed,
borderRadius: 25,
width: 50,
height: 50,
justifyContent: 'center',
alignItems: 'center',
},
headerLogoImage: {
width: 30,
height: 30,
resizeMode: 'contain',
},
headerTextContainer: {
flex: 1,
},
headerSanguAkeul: {
fontSize: 20,
fontWeight: 'bold',
color: Colors.primaryRed,
},
headerCigaleuh: {
fontSize: 16,
color: Colors.primaryRed,
},
searchBarContainer: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: Colors.white,
borderRadius: 10,
marginHorizontal: 20,
marginTop: 15,
marginBottom: 20,
paddingHorizontal: 15,
paddingVertical: 8,
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 1.5,
},
searchInput: {
flex: 1,
fontSize: 16,
color: Colors.darkGreyText,
paddingVertical: 0,
},
searchIconImage: {
width: 24,
height: 24,
resizeMode: 'contain',
marginLeft: 10,
},
contentScrollViewContent: {
paddingHorizontal: 20,
paddingBottom: 20,
},
cardContainer: {
alignItems: 'center',
borderRadius: 15,
padding: 15,
marginBottom: 15,
elevation: 3,
shadowColor: '#000',
shadowOffset: { width: 0, height: 3 },
shadowOpacity: 0.2,
shadowRadius: 3,
},
cardContent: {
flex: 1,
},
cardTitle: {
fontSize: 22,
fontWeight: 'bold',
color: Colors.white,
marginBottom: 5,
},
cardDescription: {
fontSize: 14,
color: Colors.white,
lineHeight: 20,
},
cardImage: {
width: 100,
height: 100,
borderRadius: 10,
resizeMode: 'cover',
},
bottomNav: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
backgroundColor: Colors.white,
borderTopWidth: 1,
borderTopColor: '#EEE',
height: 60,
elevation: 5,
shadowColor: '#000',
shadowOffset: { width: 0, height: -3 },
shadowOpacity: 0.1,
shadowRadius: 3,
marginBottom: 40
},
navItem: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 5,
},
navImage: {
width: 28,
height: 28,
resizeMode: 'contain',
tintColor: Colors.greyText,
},
});
export default MainScreen;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment