upload 14/8

This commit is contained in:
2025-08-14 14:31:37 +07:00
parent 2e949b8da3
commit 78bb7a0182
15 changed files with 706 additions and 5 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

BIN
assets/images/icon-tel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/images/icon-web.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,298 @@
import React, { useState } from "react";
import {
View,
Text,
StyleSheet,
FlatList,
Image,
TouchableOpacity,
ScrollView,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
import ReviewModal from "@components/product/FormReview";
const reviews = [
{
id: "1",
name: "Dino",
time: "10:00pm 20/02/2025",
title: "Laptop Gaming Asus ROG 16GB",
content:
"Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
images: [
require("../../../assets/images/small-product-detail.png"),
require("../../../assets/images/small-product-detail.png"),
require("../../../assets/images/small-product-detail.png"),
],
star: 5,
},
{
id: "2",
name: "Dino",
time: "10:00pm 20/02/2025",
title: "Laptop Gaming Asus ROG 16GB",
content:
"Lorem Ipsum is simply dummy text of the printing and typesetting industry.",
images: [
require("../../../assets/images/small-product-detail.png"),
require("../../../assets/images/small-product-detail.png"),
],
star: 4,
},
];
const renderStars = (count: number) => {
return (
<View style={{ flexDirection: "row" }}>
{Array.from({ length: 5 }).map((_, index) => (
<Ionicons
key={index}
name="star"
size={16}
color={index < count ? "#ff7a00" : "#d9d9d9"}
/>
))}
</View>
);
};
const ReviewSection = () => {
const [showReviewModal, setShowReviewModal] = useState(false);
return (
<View style={styles.BoxReview}>
{/* Header */}
<View style={styles.header}>
<Text style={styles.headerTitle}>Đánh giá</Text>
</View>
<View style={styles.content}>
{/* Right */}
<View style={styles.right}>
<FlatList
data={reviews}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<View style={styles.reviewItem}>
<View style={styles.avatarBox}>
<Image
source={require("../../../assets/images/avartar-review-1.png")}
style={styles.avatar}
/>
<View>
<View
style={{ flexDirection: "row", alignItems: "center" }}
>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.time}>{item.time}</Text>
</View>
<Text style={styles.star}>{renderStars(item.star)}</Text>
</View>
</View>
<View style={styles.reviewContent}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.contentText}>{item.content}</Text>
<View style={styles.imageList}>
{item.images.map((img, index) => (
<Image
key={index}
source={img}
style={styles.reviewImage}
/>
))}
</View>
<View style={styles.btnRow}>
<TouchableOpacity>
<Text style={styles.btnLink}>
Bình luận <Text style={styles.black}>(23)</Text>
</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.btnLink}>
Thích <Text style={styles.black}>(23)</Text>
</Text>
</TouchableOpacity>
</View>
</View>
</View>
)}
/>
<TouchableOpacity
style={{
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
}}
>
<Text style={styles.moreBtn}>
Xem thêm <Text style={styles.moreBold}>23</Text> bình luận khác
</Text>
<Ionicons
name="chevron-down"
style={{ marginLeft: 5 }}
size={16}
color="#FF7A00"
/>
</TouchableOpacity>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
BoxReview: {
padding: 10,
backgroundColor: "#fff",
marginTop: 20,
borderRadius: 8,
borderWidth: 1,
borderColor: "#D4D4D4",
},
header: {
flexDirection: "row",
justifyContent: "space-between",
borderBottomWidth: 1,
borderBottomColor: "#B1B1B1",
paddingBottom: 15,
},
headerTitle: {
fontSize: 16,
fontWeight: "bold",
},
sortBox: {
borderWidth: 1,
borderColor: "#B1B1B1",
paddingHorizontal: 10,
height: 45,
justifyContent: "center",
borderRadius: 4,
},
content: {
gap: 25,
marginTop: 20,
},
left: {
width: "100%",
},
totalReview: {
textAlign: "center",
fontSize: 22,
fontWeight: "bold",
paddingBottom: 5,
},
ratingRow: {
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginBottom: 10,
},
star: {
fontSize: 16,
},
ratingText: {
marginLeft: 5,
fontSize: 16,
fontWeight: 700,
},
ratingBreakdown: {
borderTopWidth: 1,
borderTopColor: "#E4E4E4",
paddingTop: 10,
},
ratingLine: {
flexDirection: "row",
justifyContent: "space-between",
marginBottom: 10,
},
reviewBtnArea: {
borderTopWidth: 1,
borderTopColor: "#E4E4E4",
paddingTop: 10,
marginTop: 20,
},
reviewPrompt: {
textAlign: "center",
marginTop: 10,
},
reviewBtn: {
marginTop: 10,
height: 40,
backgroundColor: "#FF7A00",
justifyContent: "center",
alignItems: "center",
borderRadius: 4,
},
reviewBtnText: {
color: "#fff",
},
right: {
width: "100%",
},
reviewItem: {
marginBottom: 15,
paddingBottom: 15,
borderBottomWidth: 1,
borderBottomColor: "rgba(228, 228, 228, 1)",
},
avatarBox: {
flexDirection: "row",
alignContent: "center",
width: "100%",
alignItems: "center",
marginRight: 20,
},
avatar: {
width: 30,
height: 30,
borderRadius: 40,
marginRight: 10,
},
name: {
fontWeight: "bold",
marginRight: 10,
},
time: {
fontSize: 12,
textAlign: "center",
},
reviewContent: {
flex: 1,
},
title: {
fontWeight: "600",
marginBottom: 5,
},
contentText: {
marginBottom: 5,
},
imageList: {
flexDirection: "row",
marginBottom: 10,
},
reviewImage: {
width: 80,
height: 80,
marginRight: 10,
},
btnRow: {
flexDirection: "row",
},
btnLink: {
color: "#1877F2",
marginRight: 15,
},
black: {
color: "#000",
},
moreBtn: {
color: "#FF7A00",
},
moreBold: {
fontWeight: "bold",
},
});
export default ReviewSection;

View File

@@ -0,0 +1,119 @@
import React from "react";
import { View, StyleSheet, Image, Text } from "react-native";
const CompanyInfo = () => {
const infoItems = [
{
icon: require("../../../assets/images/icon_store_gray.png"),
label: "Lĩnh vực",
value: "Chuyên sửa chữa PC, laptop, linh phụ kiện máy tính",
},
{
icon: require("../../../assets/images/icon-mohinh.png"),
label: "Mô hình",
value: "Cá nhân",
},
{
icon: require("../../../assets/images/icon-times.png"),
label: "Năm hoạt động",
value: "5 năm",
},
{
icon: require("../../../assets/images/icon-locahost.png"),
label: "Địa chỉ",
value:
"Tầng 7, toà nhà số 198 Nguyễn Thị Minh Khai, phường 6, quận 3, TP. Hồ Chí Minh",
},
{
icon: require("../../../assets/images/icon-vipham.png"),
label: "Phạm vi hoạt động",
value: "Tại cửa hàng / Bán kính quanh 20km",
},
{
icon: require("../../../assets/images/icon-web.png"),
label: "Website",
value: "https://www.anphatpc.com.vn/",
isLink: true,
},
{
icon: require("../../../assets/images/icon-tel.png"),
label: "Tel",
value: "1900 0323 0918 557 006",
},
{
icon: require("../../../assets/images/icon-email.png"),
label: "Gmail",
value: "Giang@anphatpc.com.vn",
},
];
return (
<View style={styles.container}>
<Text style={styles.title}>Thông tin</Text>
<View style={styles.boxFlex}>
{infoItems.map((item, index) => (
<View key={index} style={styles.items}>
<View style={styles.infoRow}>
<Image source={item.icon} style={styles.icon} />
<Text style={styles.label}>{item.label}</Text>
</View>
<Text style={[styles.value, item.isLink && styles.linkValue]}>
{item.value}
</Text>
</View>
))}
</View>
</View>
);
};
export default CompanyInfo;
const styles = StyleSheet.create({
container: {
borderColor: "rgba(212, 212, 212, 1)",
borderRadius: 12,
borderWidth: 1,
marginTop: 9,
padding: 10,
backgroundColor: "#fff",
},
boxFlex: {},
items: {
flexDirection: "row",
gap: 10,
marginTop: 10,
},
title: {
fontSize: 16,
fontWeight: "700",
color: "rgba(0, 0, 0, 1)",
},
infoRow: {
width: 140,
flexDirection: "row",
alignItems: "center",
},
icon: {
width: 20,
height: 20,
marginRight: 6,
resizeMode: "contain",
},
label: {
fontSize: 13,
fontWeight: "400",
color: "#303030",
},
valueContainer: {
alignSelf: "stretch",
marginTop: 10,
},
value: {
fontSize: 13,
fontWeight: "400",
color: "#303030",
},
linkValue: {
color: "rgba(24, 119, 242, 1)",
},
});

View File

@@ -34,7 +34,8 @@ export default ContactForm;
const styles = StyleSheet.create({
container: {
marginTop: 56,
marginTop: 20,
marginBottom: 20,
},
headerSection: {
position: "relative",
@@ -71,6 +72,7 @@ const styles = StyleSheet.create({
},
formSection: {
padding: 12,
backgroundColor: "#fff",
},
inputField: {
borderWidth: 1,

View File

@@ -0,0 +1,113 @@
import React from "react";
import { View, StyleSheet, Text, Image } from "react-native";
const ShowroomSection = () => {
return (
<View style={styles.container}>
<Text style={styles.title}>HỆ THỐNG SHOWROOM</Text>
<View style={styles.divider} />
<View style={styles.content}>
<View style={styles.itemShoroom}>
<Image
source={require("../../../assets/images/icon-showroom-gray.png")}
style={styles.showroomImage}
/>
<Text style={styles.addressList}>
Showroom 1: 49 Thái - Đng Đa - Nội
</Text>
</View>
<View style={styles.itemShoroom}>
<Image
source={require("../../../assets/images/icon-showroom-gray.png")}
style={styles.showroomImage}
/>
<Text style={styles.addressList}>
Showroom 2: 151 Thanh Nghị - Hai Trưng - Nội
</Text>
</View>
<View style={styles.itemShoroom}>
<Image
source={require("../../../assets/images/icon-showroom-gray.png")}
style={styles.showroomImage}
/>
<Text style={styles.addressList}>
Showroom 3: 63 Trần Thái Tông - Cầu Giấy - Nội
</Text>
</View>
<View style={styles.itemShoroom}>
<Image
source={require("../../../assets/images/icon-showroom-gray.png")}
style={styles.showroomImage}
/>
<Text style={styles.addressList}>
Showroom 4: 158 - 160 Thường Kiệt - Quận 10 - TPHCM
</Text>
</View>
<View style={styles.itemShoroom}>
<Image
source={require("../../../assets/images/icon-showroom-gray.png")}
style={styles.showroomImage}
/>
<Text style={styles.addressList}>
Showroom 5: 330-332 Văn Tần - P. 5 - Q. 3 - TPHCM
</Text>
</View>
<View style={styles.itemShoroom}>
<Image
source={require("../../../assets/images/icon-showroom-gray.png")}
style={styles.showroomImage}
/>
<Text style={styles.addressList}>
Showroom 6: Số 51 Trần Hưng Đo - Đi Phúc - Bắc Ninh
</Text>
</View>
</View>
</View>
);
};
export default ShowroomSection;
const styles = StyleSheet.create({
container: {
borderRadius: 12,
borderWidth: 1,
borderColor: "rgba(212, 212, 212, 1)",
padding: 10,
marginTop: 12,
backgroundColor: "#fff",
},
content: {},
title: {
fontSize: 14,
fontWeight: "700",
color: "rgba(0, 0, 0, 1)",
textTransform: "uppercase",
},
divider: {
height: 1,
backgroundColor: "#E3E3E3",
borderWidth: 1,
borderColor: "rgba(227, 227, 227, 1)",
marginTop: 15,
},
itemShoroom: {
flexDirection: "row",
alignItems: "center",
gap: 9,
marginTop: 10,
},
imageGrid: {
flexDirection: "column",
},
showroomImage: {
width: 20,
height: 20,
},
addressList: {
fontSize: 11,
fontWeight: "400",
color: "rgba(0, 0, 0, 1)",
flex: 1,
},
});

View File

@@ -0,0 +1,15 @@
import React, { useState } from "react";
import {
View,
Text,
TextInput,
TouchableOpacity,
ScrollView,
Image,
StyleSheet,
Dimensions,
ImageBackground,
} from "react-native";
import { useNavigation, NavigationProp } from "@react-navigation/native";
import AppLayout from "@layouts/AppLayout";
import { Ionicons } from "@expo/vector-icons";

View File

@@ -13,9 +13,28 @@ import {
import { useNavigation, NavigationProp } from "@react-navigation/native";
import AppLayout from "@layouts/AppLayout";
import { Ionicons } from "@expo/vector-icons";
import CompanyInfo from "@components/repair/CompanyInfo";
import BoxReview from "@components/repair/BoxReview";
import ShowroomSection from "@components/repair/ShowroomSection";
import ContactForm from "@components/repair/ContactForm";
const { width } = Dimensions.get("window");
const renderStars = (count: number) => {
return (
<View style={{ flexDirection: "row" }}>
{Array.from({ length: 5 }).map((_, index) => (
<Ionicons
key={index}
name="star"
size={14}
color={index < count ? "#ff7a00" : "#d9d9d9"}
/>
))}
</View>
);
};
export default function DetailRepairAddress() {
const navigation = useNavigation<NavigationProp<any>>();
@@ -41,11 +60,69 @@ export default function DetailRepairAddress() {
</View>
</View>
<Text>Danh sách đa chỉ sửa chữa</Text>
<View>
<Image />
<Text style={{ fontWeight: "bold" }}>Danh sách đa chỉ sửa chữa</Text>
<View style={styles.companyCard}>
<Image
source={require("../../../assets/images/logo-anphat.png")}
style={styles.companyLogo}
/>
<View style={styles.companyInfo}>
<Text style={styles.companyName}>An Phát</Text>
<Text style={styles.companyFullName}>
CÔNG TY CỔ PHẦN THƯƠNG MẠI MÁY TÍNH AN PHÁT
</Text>
<View style={styles.ratingContainer}>
{renderStars(4)}
<Text style={styles.rating}>4.6/5</Text>
<Text style={styles.reviewCount}>(43 đánh giá)</Text>
</View>
</View>
</View>
<View style={styles.companyDescription}>
<Text style={styles.titleCompany}>Giới thiệu</Text>
<View style={styles.dividerCompany} />
<Text style={styles.descriptionCompany}>
Thành lập vào ngày 29/03/2004, trải qua hai thập kỷ không ngừng
phát triển, An Phát Computer đã liên tục tăng trưởng, mở rộng thị
trường trở thành một trong những doanh nghiệp hàng đu trong
lĩnh vực bán buôn bán lẻ các sản phẩm, thiết bị công nghệ thông
tin, thiết bị lưu trữ, thiết bị văn phòng.
{"\n"}
Năm 2024, An Phát Computer vinh dự kỷ niệm 20 năm thành lập, đánh
dấu chặng đưng hai thập kỷ uy tín, cam kết không ngừng cải thiện
chất lượng dịch vụ, đem đến cho khách hàng những sản phẩm công
nghệ hi-end, hi-tech nhất thị trường.
{"\n\n"}
Xuyên suốt hành trình xây dựng phát triển, tiêu chí "Uy tín"
"Chuyên nghiệp" luôn đưc An Phát Computer đt lên hàng đu. Bên
cạnh đó, những sản phẩm chất lượng với mức giá cạnh tranh, dịch vụ
vấn tận tâm, chính sách bán hàng, bảo hành cùng đi ngũ cán bộ
nhân viên đưc đào tạo chuyên nghiệp cũng góp phần tạo ra những
giá trị đích thực, giúp cho An Phát Computer gặt hái đưc nhiều
thành công. Tới nay doanh nghiệp đã 07 showroom bán hàng các
thành phố lớn tại Nội, TP. Hồ Chí Minh, Bắc Ninh 01 Trung
tâm phân phối & dự án. Đến các cửa hàng thuộc hệ thống An Phát
Computer, khách hàng luôn đưc sự hài lòng với quy trình vấn
bài bản của nhân viên nhằm lựa chọn cho mình những sản phẩm ưng ý
nhất theo phương châm: "Mỗi khách hàng là một con người - một cá
thể riêng biệt, cần được tôn trọng, quan tâm và lắng nghe, thấu
hiểu và phục vụ một cách riêng biệt.".
</Text>
</View>
<CompanyInfo />
{/* thông tin công ty */}
<BoxReview />
{/* đánh giá */}
<ShowroomSection />
{/* showroom */}
<ContactForm />
{/* form liên hệ */}
</View>
</ScrollView>
</AppLayout>
);
@@ -54,7 +131,8 @@ export default function DetailRepairAddress() {
const styles = StyleSheet.create({
container: {
paddingHorizontal: 10,
backgroundColor: "#fff",
backgroundColor: "#F4F4F4",
marginBottom: 15,
},
breadcrumb: {
flexDirection: "row",
@@ -77,4 +155,80 @@ const styles = StyleSheet.create({
marginLeft: 12,
color: "#888",
},
companyCard: {
flexDirection: "row",
alignItems: "flex-start",
gap: 12,
marginTop: 10,
},
companyLogo: {
width: 80,
height: 80,
resizeMode: "contain",
borderWidth: 1,
borderColor: "#D4D4D4",
borderRadius: 4,
padding: 10,
backgroundColor: "#fff",
},
companyInfo: {
flex: 1,
},
companyName: {
fontSize: 15,
fontWeight: "700",
color: "#303030",
},
companyFullName: {
fontSize: 15,
fontWeight: "700",
color: "#303030",
marginTop: 4,
},
ratingContainer: {
flexDirection: "row",
alignItems: "center",
gap: 6,
marginTop: 4,
},
rating: {
fontSize: 13,
fontWeight: "400",
color: "#303030",
},
reviewCount: {
fontSize: 13,
fontWeight: "400",
color: "#303030",
textDecorationLine: "underline",
},
companyDescription: {
borderRadius: 8,
borderWidth: 1,
borderColor: "rgba(212, 212, 212, 1)",
paddingVertical: 16,
paddingHorizontal: 1,
marginTop: 9,
backgroundColor: "#fff",
},
titleCompany: {
fontSize: 16,
fontWeight: "700",
color: "rgba(0, 0, 0, 1)",
marginLeft: 11,
},
dividerCompany: {
height: 1,
backgroundColor: "#E3E3E3",
borderWidth: 1,
borderColor: "rgba(227, 227, 227, 1)",
marginTop: 10,
},
descriptionCompany: {
fontSize: 13,
fontWeight: "400",
color: "rgba(0, 0, 0, 1)",
lineHeight: 18,
padding: 10,
},
});