update
6
.env
@@ -1,3 +1,3 @@
|
||||
EXPO_HOME=D:/bestpc_mobile/.expo
|
||||
EXPO_CACHE_DIR=D:/bestpc_mobile/.expo/cache
|
||||
EXPO_PROJECT_DIR=D:/bestpc_mobile
|
||||
EXPO_HOME=C:/Users/tiepb/Downloads/Company/work_2025/bestpc_mobile/.expo
|
||||
EXPO_CACHE_DIR=C:/Users/tiepb/Downloads/Company/work_2025/bestpc_mobile/.expo/cache
|
||||
EXPO_PROJECT_DIR=C:/Users/tiepb/Downloads/Company/work_2025/bestpc_mobile
|
||||
|
||||
3
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
835
.idea/caches/deviceStreaming.xml
generated
Normal file
@@ -0,0 +1,835 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DeviceStreaming">
|
||||
<option name="deviceSelectionList">
|
||||
<list>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="Sony" />
|
||||
<option name="codename" value="A402SO" />
|
||||
<option name="id" value="A402SO" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Sony" />
|
||||
<option name="name" value="Xperia 10" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2520" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="27" />
|
||||
<option name="brand" value="DOCOMO" />
|
||||
<option name="codename" value="F01L" />
|
||||
<option name="id" value="F01L" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="FUJITSU" />
|
||||
<option name="name" value="F-01L" />
|
||||
<option name="screenDensity" value="360" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1280" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="OnePlus" />
|
||||
<option name="codename" value="OP535DL1" />
|
||||
<option name="id" value="OP535DL1" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="OnePlus" />
|
||||
<option name="name" value="CPH2409" />
|
||||
<option name="screenDensity" value="401" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2412" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="OnePlus" />
|
||||
<option name="codename" value="OP5552L1" />
|
||||
<option name="id" value="OP5552L1" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="OnePlus" />
|
||||
<option name="name" value="CPH2415" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2412" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="OPPO" />
|
||||
<option name="codename" value="OP573DL1" />
|
||||
<option name="id" value="OP573DL1" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="OPPO" />
|
||||
<option name="name" value="CPH2557" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="28" />
|
||||
<option name="brand" value="DOCOMO" />
|
||||
<option name="codename" value="SH-01L" />
|
||||
<option name="id" value="SH-01L" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="SHARP" />
|
||||
<option name="name" value="AQUOS sense2 SH-01L" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2160" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="a14m" />
|
||||
<option name="id" value="a14m" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-A145R" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2408" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="a15" />
|
||||
<option name="id" value="a15" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A15" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="a15x" />
|
||||
<option name="id" value="a15x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A15 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="a16x" />
|
||||
<option name="id" value="a16x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A16 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="a35x" />
|
||||
<option name="id" value="a35x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A35" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="akita" />
|
||||
<option name="id" value="akita" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 8a" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="akita" />
|
||||
<option name="id" value="akita" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 8a" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="arcfox" />
|
||||
<option name="id" value="arcfox" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="razr plus 2024" />
|
||||
<option name="screenDensity" value="360" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="1272" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="austin" />
|
||||
<option name="id" value="austin" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="moto g 5G (2022)" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="b0q" />
|
||||
<option name="id" value="b0q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S22 Ultra" />
|
||||
<option name="screenDensity" value="600" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="3088" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="b6q" />
|
||||
<option name="id" value="b6q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Flip 6" />
|
||||
<option name="screenDensity" value="340" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2640" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="32" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="bluejay" />
|
||||
<option name="id" value="bluejay" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 6a" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="caiman" />
|
||||
<option name="id" value="caiman" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9 Pro" />
|
||||
<option name="screenDensity" value="360" />
|
||||
<option name="screenX" value="960" />
|
||||
<option name="screenY" value="2142" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="caiman" />
|
||||
<option name="id" value="caiman" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9 Pro" />
|
||||
<option name="screenDensity" value="360" />
|
||||
<option name="screenX" value="960" />
|
||||
<option name="screenY" value="2142" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="comet" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="comet" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9 Pro Fold" />
|
||||
<option name="screenDensity" value="390" />
|
||||
<option name="screenX" value="2076" />
|
||||
<option name="screenY" value="2152" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="comet" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="comet" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9 Pro Fold" />
|
||||
<option name="screenDensity" value="390" />
|
||||
<option name="screenX" value="2076" />
|
||||
<option name="screenY" value="2152" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="29" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="crownqlteue" />
|
||||
<option name="id" value="crownqlteue" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Note9" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="2220" />
|
||||
<option name="screenY" value="1080" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="dm2q" />
|
||||
<option name="id" value="dm2q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="S23 Plus" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="dm3q" />
|
||||
<option name="id" value="dm3q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S23 Ultra" />
|
||||
<option name="screenDensity" value="600" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="3088" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="dubai" />
|
||||
<option name="id" value="dubai" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="edge 30" />
|
||||
<option name="screenDensity" value="405" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="e1q" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="e1q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S24" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="e3q" />
|
||||
<option name="id" value="e3q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S24 Ultra" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="3120" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="eos" />
|
||||
<option name="id" value="eos" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Eos" />
|
||||
<option name="screenDensity" value="320" />
|
||||
<option name="screenX" value="384" />
|
||||
<option name="screenY" value="384" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="eqe" />
|
||||
<option name="id" value="eqe" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="edge 50 pro" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1220" />
|
||||
<option name="screenY" value="2712" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="felix" />
|
||||
<option name="id" value="felix" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel Fold" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="2208" />
|
||||
<option name="screenY" value="1840" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="felix" />
|
||||
<option name="id" value="felix" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel Fold" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="2208" />
|
||||
<option name="screenY" value="1840" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="felix_camera" />
|
||||
<option name="id" value="felix_camera" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel Fold (Camera-enabled)" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="2208" />
|
||||
<option name="screenY" value="1840" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="fogona" />
|
||||
<option name="id" value="fogona" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="moto g play - 2024" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="fogos" />
|
||||
<option name="id" value="fogos" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="moto g34 5G" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="g0q" />
|
||||
<option name="id" value="g0q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-S906U1" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gta9pwifi" />
|
||||
<option name="id" value="gta9pwifi" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-X210" />
|
||||
<option name="screenDensity" value="240" />
|
||||
<option name="screenX" value="1200" />
|
||||
<option name="screenY" value="1920" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gts7lwifi" />
|
||||
<option name="id" value="gts7lwifi" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-T870" />
|
||||
<option name="screenDensity" value="340" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gts7xllite" />
|
||||
<option name="id" value="gts7xllite" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-T738U" />
|
||||
<option name="screenDensity" value="340" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gts8uwifi" />
|
||||
<option name="formFactor" value="Tablet" />
|
||||
<option name="id" value="gts8uwifi" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Tab S8 Ultra" />
|
||||
<option name="screenDensity" value="320" />
|
||||
<option name="screenX" value="1848" />
|
||||
<option name="screenY" value="2960" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gts8wifi" />
|
||||
<option name="formFactor" value="Tablet" />
|
||||
<option name="id" value="gts8wifi" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Tab S8" />
|
||||
<option name="screenDensity" value="274" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gts9fe" />
|
||||
<option name="id" value="gts9fe" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Tab S9 FE 5G" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="2304" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gts9wifi" />
|
||||
<option name="id" value="gts9wifi" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-X710" />
|
||||
<option name="screenDensity" value="340" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="husky" />
|
||||
<option name="id" value="husky" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 8 Pro" />
|
||||
<option name="screenDensity" value="390" />
|
||||
<option name="screenX" value="1008" />
|
||||
<option name="screenY" value="2244" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="30" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="java" />
|
||||
<option name="id" value="java" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="G20" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="komodo" />
|
||||
<option name="id" value="komodo" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9 Pro XL" />
|
||||
<option name="screenDensity" value="360" />
|
||||
<option name="screenX" value="1008" />
|
||||
<option name="screenY" value="2244" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="komodo" />
|
||||
<option name="id" value="komodo" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9 Pro XL" />
|
||||
<option name="screenDensity" value="360" />
|
||||
<option name="screenX" value="1008" />
|
||||
<option name="screenY" value="2244" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="lion" />
|
||||
<option name="id" value="lion" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="moto g04" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1612" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="lynx" />
|
||||
<option name="id" value="lynx" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 7a" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="lyriq" />
|
||||
<option name="id" value="lyriq" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="edge 40" />
|
||||
<option name="screenDensity" value="400" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="manaus" />
|
||||
<option name="id" value="manaus" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="edge 40 neo" />
|
||||
<option name="screenDensity" value="400" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="maui" />
|
||||
<option name="id" value="maui" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="moto g play - 2023" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="o1q" />
|
||||
<option name="id" value="o1q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S21" />
|
||||
<option name="screenDensity" value="421" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="31" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="oriole" />
|
||||
<option name="id" value="oriole" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 6" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="pa3q" />
|
||||
<option name="id" value="pa3q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S25 Ultra" />
|
||||
<option name="screenDensity" value="600" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="3120" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="panther" />
|
||||
<option name="id" value="panther" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 7" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="q5q" />
|
||||
<option name="id" value="q5q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Z Fold5" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1812" />
|
||||
<option name="screenY" value="2176" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="q6q" />
|
||||
<option name="id" value="q6q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Z Fold6" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1856" />
|
||||
<option name="screenY" value="2160" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="30" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="r11" />
|
||||
<option name="formFactor" value="Wear OS" />
|
||||
<option name="id" value="r11" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel Watch" />
|
||||
<option name="screenDensity" value="320" />
|
||||
<option name="screenX" value="384" />
|
||||
<option name="screenY" value="384" />
|
||||
<option name="type" value="WEAR_OS" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="r11q" />
|
||||
<option name="id" value="r11q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-S711U" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="30" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="redfin" />
|
||||
<option name="id" value="redfin" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 5" />
|
||||
<option name="screenDensity" value="440" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="shiba" />
|
||||
<option name="id" value="shiba" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 8" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="t2q" />
|
||||
<option name="id" value="t2q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S21 Plus" />
|
||||
<option name="screenDensity" value="394" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="tangorpro" />
|
||||
<option name="formFactor" value="Tablet" />
|
||||
<option name="id" value="tangorpro" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel Tablet" />
|
||||
<option name="screenDensity" value="320" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="tegu" />
|
||||
<option name="id" value="tegu" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9a" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2424" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="tokay" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="tokay" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2424" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="tokay" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="tokay" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2424" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="xcover7" />
|
||||
<option name="id" value="xcover7" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-G556B" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2408" />
|
||||
</PersistentDeviceSelectionData>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
13
.idea/deviceManager.xml
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DeviceTable">
|
||||
<option name="columnSorters">
|
||||
<list>
|
||||
<ColumnSorterState>
|
||||
<option name="column" value="Name" />
|
||||
<option name="order" value="ASCENDING" />
|
||||
</ColumnSorterState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
47
App.tsx
@@ -1,53 +1,14 @@
|
||||
import { StatusBar } from "expo-status-bar";
|
||||
import { StyleSheet, ScrollView } from "react-native";
|
||||
import { SafeAreaProvider } from "react-native-safe-area-context";
|
||||
import React from "react";
|
||||
import { NavigationContainer } from "@react-navigation/native";
|
||||
import {
|
||||
createStackNavigator,
|
||||
StackScreenProps,
|
||||
} from "@react-navigation/stack";
|
||||
import {
|
||||
createDrawerNavigator,
|
||||
DrawerItemList,
|
||||
DrawerItem,
|
||||
DrawerContentScrollView,
|
||||
} from "@react-navigation/drawer";
|
||||
|
||||
import Header from "./src/components/header/Header";
|
||||
import Footer from "./src/components/footer/Footer";
|
||||
import HomePage from "./src/screens/HomeScreen";
|
||||
import { SafeAreaProvider } from "react-native-safe-area-context";
|
||||
import AppNavigator from "./src/navigation/AppNavigator";
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<SafeAreaProvider>
|
||||
<Header />
|
||||
<NavigationContainer>
|
||||
<AllPage />
|
||||
<AppNavigator />
|
||||
</NavigationContainer>
|
||||
{/* <Footer /> */}
|
||||
</SafeAreaProvider>
|
||||
);
|
||||
}
|
||||
const Drawer = createDrawerNavigator();
|
||||
const Stack = createStackNavigator();
|
||||
|
||||
const AllPage = () => {
|
||||
return (
|
||||
<Stack.Navigator
|
||||
initialRouteName="homepage"
|
||||
screenOptions={{
|
||||
headerShown: false, // Ẩn header cho tất cả màn hình
|
||||
}}
|
||||
>
|
||||
<Stack.Screen name="homepage" component={HomePage} />
|
||||
</Stack.Navigator>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
maxWidth: 480,
|
||||
},
|
||||
});
|
||||
|
||||
BIN
assets/images/avartar-review-1.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
assets/images/avartar-review-2.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
assets/images/avartar-review-3.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
assets/images/avartar.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
assets/images/avartar_acc.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
assets/images/banner-right-slider-1.png
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
assets/images/banner-right-slider-2.png
Normal file
|
After Width: | Height: | Size: 454 KiB |
BIN
assets/images/banner-right-slider-3.png
Normal file
|
After Width: | Height: | Size: 464 KiB |
BIN
assets/images/banner-right-slider-4.png
Normal file
|
After Width: | Height: | Size: 415 KiB |
BIN
assets/images/banner-sale-1.png
Normal file
|
After Width: | Height: | Size: 488 KiB |
BIN
assets/images/banner-sale-2.png
Normal file
|
After Width: | Height: | Size: 397 KiB |
BIN
assets/images/banner-sale-3.png
Normal file
|
After Width: | Height: | Size: 386 KiB |
BIN
assets/images/banner-sale-4.png
Normal file
|
After Width: | Height: | Size: 268 KiB |
BIN
assets/images/big-product-detail-1.jpg
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
assets/images/big-product-detail-2.jpg
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
assets/images/big-product-detail-3.jpg
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
assets/images/big-product-detail-4.jpg
Normal file
|
After Width: | Height: | Size: 275 KiB |
BIN
assets/images/big-product-detail.jpg
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
assets/images/big-product-detail.png
Normal file
|
After Width: | Height: | Size: 357 KiB |
BIN
assets/images/category-avatar.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
assets/images/icon_heart.png
Normal file
|
After Width: | Height: | Size: 859 B |
BIN
assets/images/icon_map.png
Normal file
|
After Width: | Height: | Size: 920 B |
BIN
assets/images/image-article.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
assets/images/logo-anphat.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
assets/images/logo-footer.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
assets/images/logo-gearvn.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
assets/images/logo-hacom.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
assets/images/promotions-1.png
Normal file
|
After Width: | Height: | Size: 543 KiB |
BIN
assets/images/promotions-2.png
Normal file
|
After Width: | Height: | Size: 352 KiB |
BIN
assets/images/promotions-3.png
Normal file
|
After Width: | Height: | Size: 452 KiB |
BIN
assets/images/promotions-4.png
Normal file
|
After Width: | Height: | Size: 464 KiB |
BIN
assets/images/small-product-detail.png
Normal file
|
After Width: | Height: | Size: 536 KiB |
18
babel.config.js
Normal file
@@ -0,0 +1,18 @@
|
||||
module.exports = {
|
||||
presets: ['babel-preset-expo'],
|
||||
plugins: [
|
||||
[
|
||||
'module-resolver',
|
||||
{
|
||||
root: ['./src'],
|
||||
alias: {
|
||||
'@components': './src/components',
|
||||
'@layouts': './src/layouts',
|
||||
'@screens': './src/screens',
|
||||
'@assets': './src/assets',
|
||||
'@navigation': './src/navigation',
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
1
index.ts
@@ -6,3 +6,4 @@ import App from './App';
|
||||
// It also ensures that whether you load the app in Expo Go or in a native build,
|
||||
// the environment is set up appropriately
|
||||
registerRootComponent(App);
|
||||
|
||||
|
||||
39049
package-lock.json
generated
14
package.json
@@ -14,30 +14,40 @@
|
||||
"@expo/vector-icons": "^14.1.0",
|
||||
"@react-native-picker/picker": "^2.11.0",
|
||||
"@react-navigation/drawer": "^7.3.12",
|
||||
"@react-navigation/native": "^7.1.9",
|
||||
"@react-navigation/native": "^7.1.14",
|
||||
"@react-navigation/native-stack": "^7.3.13",
|
||||
"@react-navigation/stack": "^7.3.2",
|
||||
"dotenv": "^16.5.0",
|
||||
"expo-cli": "^4.9.1",
|
||||
"expo-image-picker": "~16.1.4",
|
||||
"expo-linear-gradient": "~14.1.4",
|
||||
"expo-status-bar": "~2.2.3",
|
||||
"hermes-engine": "^0.11.0",
|
||||
"lodash": "^4.17.21",
|
||||
"metro-runtime": "^0.82.3",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-native": "^0.79.2",
|
||||
"react-native-collapsible": "^1.6.2",
|
||||
"react-native-gesture-handler": "~2.24.0",
|
||||
"react-native-reanimated": "~3.17.4",
|
||||
"react-native-reanimated-carousel": "^4.0.2",
|
||||
"react-native-render-html": "^6.3.4",
|
||||
"react-native-safe-area-context": "^5.4.0",
|
||||
"react-native-screens": "~4.10.0",
|
||||
"react-native-swiper": "^1.6.0",
|
||||
"react-native-web": "^0.20.0",
|
||||
"react-native-webview": "13.13.5",
|
||||
"react-navigation": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/plugin-transform-private-methods": "^7.27.1",
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/react": "~19.0.10",
|
||||
"@types/react-native": "^0.73.0",
|
||||
"babel-plugin-module-resolver": "^5.0.2",
|
||||
"expo": "^53.0.9",
|
||||
"metro-react-native-babel-preset": "^0.77.0",
|
||||
"typescript": "~5.8.3"
|
||||
},
|
||||
"private": true
|
||||
|
||||
76
src/components/footer/ButtonFooter.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
StyleSheet,
|
||||
ScrollView,
|
||||
} from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { NavigationProp } from "@react-navigation/native";
|
||||
|
||||
type Props = {
|
||||
navigation: NavigationProp<any>;
|
||||
activeTab?: string;
|
||||
};
|
||||
const navTabs = [
|
||||
{ label: "Trang chủ", icon: "home-outline", route: "homepage" },
|
||||
{ label: "Sản phẩm", icon: "cube-outline", route: "productlist" },
|
||||
{ label: "Sửa chữa", icon: "settings-outline", route: "Repair" },
|
||||
{ label: "Hỏi đáp", icon: "help-circle-outline", route: "FAQ" },
|
||||
{ label: "Tài khoản", icon: "person-outline", route: "Account" },
|
||||
];
|
||||
|
||||
const ButtonFooter: React.FC<Props> = ({ navigation, activeTab }) => {
|
||||
return (
|
||||
<View style={styles.footerNav}>
|
||||
{navTabs.map((tab, index) => {
|
||||
const isActive = activeTab === tab.route;
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={index}
|
||||
style={styles.navItem}
|
||||
onPress={() => navigation?.navigate(tab.route)}
|
||||
>
|
||||
<Ionicons
|
||||
name={tab.icon}
|
||||
size={22}
|
||||
color={isActive ? "#4a00e0" : "#666"}
|
||||
/>
|
||||
<Text style={[styles.navLabel, isActive && styles.navLabelActive]}>
|
||||
{tab.label}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
const styles = StyleSheet.create({
|
||||
footerNav: {
|
||||
flexDirection: "row",
|
||||
borderTopWidth: 1,
|
||||
borderColor: "#ddd",
|
||||
backgroundColor: "#fff",
|
||||
paddingVertical: 8,
|
||||
justifyContent: "space-around",
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
width: "100%",
|
||||
},
|
||||
navItem: {
|
||||
alignItems: "center",
|
||||
flex: 1,
|
||||
},
|
||||
navLabel: {
|
||||
fontSize: 12,
|
||||
color: "#666",
|
||||
marginTop: 2,
|
||||
},
|
||||
navLabelActive: {
|
||||
color: "#4a00e0",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
});
|
||||
|
||||
export default ButtonFooter;
|
||||
@@ -1,101 +1,148 @@
|
||||
import * as React from "react";
|
||||
import { View, Text, StyleSheet, Image, TouchableOpacity } from "react-native";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
StyleSheet,
|
||||
ScrollView,
|
||||
Linking,
|
||||
Dimensions,
|
||||
} from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import Collapsible from "react-native-collapsible";
|
||||
import { NavigationProp } from "@react-navigation/native";
|
||||
|
||||
type FooterItemProps = {
|
||||
label: string;
|
||||
icon: string;
|
||||
var winWidth = Dimensions.get("window").width; //full width
|
||||
|
||||
const accordionData = [
|
||||
{
|
||||
title: "Về chúng tôi",
|
||||
links: [
|
||||
{ title: "Độc quyền", route: "" },
|
||||
{ title: "Mua online", route: "" },
|
||||
{ title: "Bộ sưu tập", route: "" },
|
||||
{ title: "Tin tức", route: "article" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Tuyển dụng",
|
||||
links: [
|
||||
{ title: "Liên hệ", route: "contact" },
|
||||
{ title: "Điều khoản", route: "" },
|
||||
{ title: "Chính sách bảo mật", route: "" },
|
||||
{ title: "Trở thành đối tác", route: "" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Liên kết",
|
||||
links: [{ title: "Hurasoft.com", route: "https://www.hurasoft.vn" }],
|
||||
},
|
||||
{
|
||||
title: "Giới thiệu",
|
||||
content: "Chào mừng bạn đến với ứng dụng của chúng tôi.",
|
||||
},
|
||||
];
|
||||
|
||||
type Props = {
|
||||
navigation: NavigationProp<any>;
|
||||
activeTab?: string;
|
||||
};
|
||||
|
||||
const FooterItem = ({ label, icon }: FooterItemProps) => (
|
||||
<TouchableOpacity style={styles.footerItem}>
|
||||
<Text style={styles.footerItemText}>{label}</Text>
|
||||
<Image
|
||||
source={{ uri: icon }}
|
||||
style={styles.footerItemIcon}
|
||||
resizeMode="contain"
|
||||
const Footer: React.FC<Props> = ({ navigation, activeTab = "homepage" }) => {
|
||||
const [activeIndex, setActiveIndex] = useState(null);
|
||||
|
||||
const toggleAccordion = (index: any) => {
|
||||
setActiveIndex(index === activeIndex ? null : index);
|
||||
};
|
||||
|
||||
const handleLinkPress = (route: string) => {
|
||||
if (route.startsWith("http")) {
|
||||
// Mở link ngoài nếu là URL
|
||||
Linking.openURL(route);
|
||||
} else {
|
||||
navigation?.navigate(route);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.footer}>
|
||||
<View style={styles.spacer} />
|
||||
<ScrollView style={styles.accordionContainer}>
|
||||
{accordionData.map((item, index) => (
|
||||
<View key={index}>
|
||||
<TouchableOpacity
|
||||
style={styles.accordionHeader}
|
||||
onPress={() => toggleAccordion(index)}
|
||||
>
|
||||
<Text style={styles.accordionTitle}>{item.title}</Text>
|
||||
<Ionicons
|
||||
name={activeIndex === index ? "chevron-up" : "chevron-down"}
|
||||
size={20}
|
||||
color="#333"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
const Footer = () => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.spacer} />
|
||||
<View style={styles.content}>
|
||||
<FooterItem
|
||||
label="Về chúng tôi"
|
||||
icon="https://cdn.builder.io/api/v1/image/assets/TEMP/0f5cda0be55412240422e2274330e3f6e64023d3?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756"
|
||||
/>
|
||||
<FooterItem
|
||||
label="Tuyển dụng"
|
||||
icon="https://cdn.builder.io/api/v1/image/assets/TEMP/0f5cda0be55412240422e2274330e3f6e64023d3?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756"
|
||||
/>
|
||||
<FooterItem
|
||||
label="Liên kết"
|
||||
icon="https://cdn.builder.io/api/v1/image/assets/TEMP/0f5cda0be55412240422e2274330e3f6e64023d3?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756"
|
||||
/>
|
||||
<FooterItem
|
||||
label="Giới thiệu"
|
||||
icon="https://cdn.builder.io/api/v1/image/assets/TEMP/5263024b89e68e21be091071a684ede939b2cbf7?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756"
|
||||
/>
|
||||
<Image
|
||||
source={{
|
||||
uri: "https://cdn.builder.io/api/v1/image/assets/TEMP/e7727a56c76a2e7c02cd1646e68e8b20cefb30e1?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756",
|
||||
}}
|
||||
style={styles.logo}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
<Collapsible collapsed={activeIndex !== index}>
|
||||
{item.links?.map((link, linkIndex) => (
|
||||
<TouchableOpacity
|
||||
key={linkIndex}
|
||||
style={styles.linkItem}
|
||||
onPress={() => handleLinkPress(link.route)}
|
||||
>
|
||||
<Text style={styles.linkText}>{link.title}</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</Collapsible>
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
alignSelf: "stretch",
|
||||
marginTop: 28,
|
||||
footer: {
|
||||
width: "100%",
|
||||
paddingBottom: 21,
|
||||
marginTop: 20,
|
||||
},
|
||||
spacer: {
|
||||
display: "flex",
|
||||
minHeight: 10,
|
||||
width: "100%",
|
||||
backgroundColor: "#1c039b",
|
||||
},
|
||||
content: {
|
||||
marginTop: 17,
|
||||
width: "100%",
|
||||
accordionContainer: {
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingTop: 16,
|
||||
marginBottom: 60,
|
||||
width: winWidth - 10,
|
||||
},
|
||||
footerItem: {
|
||||
borderRadius: 4,
|
||||
display: "flex",
|
||||
paddingLeft: 9,
|
||||
paddingRight: 9,
|
||||
paddingTop: 6,
|
||||
paddingBottom: 13,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
accordionHeader: {
|
||||
backgroundColor: "#f5f5f5",
|
||||
padding: 14,
|
||||
borderRadius: 8,
|
||||
marginBottom: 8,
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
},
|
||||
footerItemText: {
|
||||
color: "#444",
|
||||
fontFamily: "Shopee Display, -apple-system, Roboto, Helvetica, sans-serif",
|
||||
fontSize: 13,
|
||||
fontWeight: "700",
|
||||
accordionTitle: {
|
||||
fontSize: 16,
|
||||
color: "#333",
|
||||
fontWeight: 700,
|
||||
},
|
||||
footerItemIcon: {
|
||||
width: 11,
|
||||
height: 6,
|
||||
marginTop: 7,
|
||||
accordionContent: {
|
||||
backgroundColor: "#fff",
|
||||
padding: 12,
|
||||
marginBottom: 10,
|
||||
color: "#555",
|
||||
},
|
||||
logo: {
|
||||
width: 95,
|
||||
height: 40,
|
||||
marginTop: 17,
|
||||
marginLeft: 10,
|
||||
linkItem: {
|
||||
paddingVertical: 8,
|
||||
paddingLeft: 20,
|
||||
},
|
||||
linkText: {
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -223,20 +223,22 @@ const styles = StyleSheet.create({
|
||||
borderRadius: 4,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingTop: 6,
|
||||
paddingBottom: 6,
|
||||
height: 32,
|
||||
lineHeight: 32,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
backgroundColor: "#FFFFFF",
|
||||
},
|
||||
searchInput: {
|
||||
flex: 1,
|
||||
fontSize: 12,
|
||||
fontFamily: "Roboto, -apple-system, Roboto, Helvetica, sans-serif",
|
||||
fontWeight: "500",
|
||||
color: "#000000",
|
||||
height: 32,
|
||||
lineHeight: 32,
|
||||
paddingTop: 7,
|
||||
marginTop: 5,
|
||||
width: winWidth - 60,
|
||||
},
|
||||
searchIconContainer: {
|
||||
flexDirection: "row",
|
||||
|
||||
108
src/components/product/FilterDropdown.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
StyleSheet,
|
||||
FlatList,
|
||||
} from "react-native";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
|
||||
type Props = {
|
||||
options: string[];
|
||||
selected: string;
|
||||
onSelect: (val: string) => void;
|
||||
placeholder?: string;
|
||||
};
|
||||
|
||||
const FilterDropdown = ({
|
||||
options,
|
||||
selected,
|
||||
onSelect,
|
||||
placeholder,
|
||||
}: Props) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<View style={styles.dropdownContainer}>
|
||||
<TouchableOpacity
|
||||
style={styles.dropdownHeader}
|
||||
onPress={() => setOpen(!open)}
|
||||
>
|
||||
<Text style={styles.dropdownText}>
|
||||
{selected || placeholder || "Chọn"}
|
||||
</Text>
|
||||
<Feather
|
||||
name={open ? "chevron-up" : "chevron-down"}
|
||||
size={16}
|
||||
color="#333"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
|
||||
{open && (
|
||||
<View style={styles.dropdownList}>
|
||||
<FlatList
|
||||
data={options}
|
||||
keyExtractor={(item) => item}
|
||||
renderItem={({ item }) => (
|
||||
<TouchableOpacity
|
||||
style={styles.option}
|
||||
onPress={() => {
|
||||
onSelect(item);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<Text style={styles.optionText}>{item}</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default FilterDropdown;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
dropdownContainer: {
|
||||
width: 150,
|
||||
marginTop: 10,
|
||||
marginBottom: 10,
|
||||
position: "relative",
|
||||
marginRight: 10,
|
||||
},
|
||||
dropdownHeader: {
|
||||
borderWidth: 1,
|
||||
borderColor: "#ccc",
|
||||
borderRadius: 6,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 8,
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
dropdownText: {
|
||||
fontSize: 14,
|
||||
},
|
||||
dropdownList: {
|
||||
position: "absolute",
|
||||
top: 37,
|
||||
width: "100%",
|
||||
borderWidth: 1,
|
||||
borderColor: "#ccc",
|
||||
borderTopWidth: 0,
|
||||
borderRadius: 6,
|
||||
overflow: "hidden",
|
||||
maxHeight: 150,
|
||||
backgroundColor: "#fff",
|
||||
zIndex: 1000,
|
||||
},
|
||||
option: {
|
||||
padding: 10,
|
||||
},
|
||||
optionText: {
|
||||
fontSize: 14,
|
||||
},
|
||||
});
|
||||
182
src/components/product/FormReview.tsx
Normal file
@@ -0,0 +1,182 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
Modal,
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
Image,
|
||||
Pressable,
|
||||
ScrollView,
|
||||
} from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
|
||||
type Props = {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const FormReview = ({ visible, onClose }: Props) => {
|
||||
const [selectedRating, setSelectedRating] = useState<number>(0);
|
||||
const [title, setTitle] = useState("");
|
||||
const [content, setContent] = useState("");
|
||||
|
||||
const handleRating = (value: number) => {
|
||||
setSelectedRating(value);
|
||||
};
|
||||
|
||||
const renderStars = () => {
|
||||
return (
|
||||
<View style={{ flexDirection: "row" }}>
|
||||
{[1, 2, 3, 4, 5].map((i) => (
|
||||
<TouchableOpacity key={i} onPress={() => handleRating(i)}>
|
||||
<Ionicons
|
||||
name="star"
|
||||
size={28}
|
||||
color={i <= selectedRating ? "#ff7a00" : "#d9d9d9"}
|
||||
style={{ marginHorizontal: 4 }}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal visible={visible} animationType="fade" transparent>
|
||||
<View style={styles.overlay}>
|
||||
<View style={styles.container}>
|
||||
{/* Title */}
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.headerText}>Đánh giá sản phẩm</Text>
|
||||
<TouchableOpacity onPress={onClose}>
|
||||
<Text style={styles.closeBtn}>x</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<ScrollView contentContainerStyle={{ alignItems: "center" }}>
|
||||
{/* Product info */}
|
||||
<Image
|
||||
source={require("../../../assets/images/small-product-detail.png")}
|
||||
style={styles.productImg}
|
||||
/>
|
||||
<Text style={styles.productName}>
|
||||
Laptop Gaming Asus TUF FX505GE-BQ037T Core i7-8750H/Win10 (15.6"
|
||||
FHD) - Hàng Chính Hãng
|
||||
</Text>
|
||||
|
||||
{/* Rating */}
|
||||
{renderStars()}
|
||||
|
||||
{/* Title input */}
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Mời bạn nhập tiêu đề..."
|
||||
value={title}
|
||||
onChangeText={setTitle}
|
||||
/>
|
||||
|
||||
{/* Content input */}
|
||||
<TextInput
|
||||
style={[styles.input, { height: 100, textAlignVertical: "top" }]}
|
||||
placeholder="Mời bạn chia sẻ cảm nhận..."
|
||||
value={content}
|
||||
onChangeText={setContent}
|
||||
multiline
|
||||
/>
|
||||
|
||||
{/* Upload placeholder */}
|
||||
<TouchableOpacity style={styles.uploadArea}>
|
||||
<Ionicons name="image-outline" size={22} color="#1877F2" />
|
||||
<Text style={styles.uploadText}>Gửi ảnh thực tế</Text>
|
||||
<Text style={styles.uploadNote}>(tối đa 3 ảnh)</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* Submit */}
|
||||
<TouchableOpacity style={styles.submitBtn}>
|
||||
<Text style={styles.submitText}>Gửi đánh giá</Text>
|
||||
</TouchableOpacity>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default FormReview;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
overlay: {
|
||||
flex: 1,
|
||||
backgroundColor: "#00000080",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
},
|
||||
container: {
|
||||
width: "95%",
|
||||
backgroundColor: "white",
|
||||
borderRadius: 12,
|
||||
padding: 20,
|
||||
maxHeight: "90%",
|
||||
},
|
||||
header: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
borderBottomWidth: 1,
|
||||
borderColor: "#E4E4E4",
|
||||
paddingBottom: 15,
|
||||
},
|
||||
headerText: {
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
textAlign: "center",
|
||||
flex: 1,
|
||||
},
|
||||
closeBtn: {
|
||||
fontSize: 22,
|
||||
color: "#808080",
|
||||
},
|
||||
productImg: {
|
||||
width: 100,
|
||||
height: 100,
|
||||
marginVertical: 10,
|
||||
},
|
||||
productName: {
|
||||
textAlign: "center",
|
||||
marginBottom: 15,
|
||||
},
|
||||
input: {
|
||||
width: "100%",
|
||||
borderWidth: 1,
|
||||
borderColor: "#B1B1B1",
|
||||
borderRadius: 4,
|
||||
padding: 10,
|
||||
marginVertical: 10,
|
||||
},
|
||||
uploadArea: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginTop: 10,
|
||||
},
|
||||
uploadText: {
|
||||
color: "#1877F2",
|
||||
marginLeft: 5,
|
||||
},
|
||||
uploadNote: {
|
||||
paddingHorizontal: 5,
|
||||
},
|
||||
submitBtn: {
|
||||
marginTop: 15,
|
||||
height: 45,
|
||||
width: 500,
|
||||
backgroundColor: "#C8B7FF",
|
||||
borderRadius: 4,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
},
|
||||
submitText: {
|
||||
color: "white",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
});
|
||||
@@ -9,10 +9,14 @@ import {
|
||||
Dimensions,
|
||||
} from "react-native";
|
||||
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
|
||||
var winWidth = Dimensions.get("window").width; //full width
|
||||
var winHeight = Dimensions.get("window").height;
|
||||
|
||||
const ItemProduct = ({ product }: { product: any }) => {
|
||||
const navigation = useNavigation();
|
||||
|
||||
function formatCurrency(a: number | string): string {
|
||||
let b = parseFloat(a.toString())
|
||||
.toFixed(2)
|
||||
@@ -25,7 +29,10 @@ const ItemProduct = ({ product }: { product: any }) => {
|
||||
|
||||
return (
|
||||
<View style={styles.productItem}>
|
||||
<TouchableOpacity style={styles.productImage}>
|
||||
<TouchableOpacity
|
||||
onPress={() => navigation.navigate("productdetail" as never)}
|
||||
style={styles.productImage}
|
||||
>
|
||||
<Image
|
||||
source={{ uri: product.productImage.large }}
|
||||
style={styles.productImg}
|
||||
@@ -37,7 +44,9 @@ const ItemProduct = ({ product }: { product: any }) => {
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<View>
|
||||
<TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={() => navigation.navigate("productdetail" as never)}
|
||||
>
|
||||
<Text numberOfLines={2} style={styles.productName}>
|
||||
{product.productName}
|
||||
</Text>
|
||||
@@ -53,7 +62,7 @@ const ItemProduct = ({ product }: { product: any }) => {
|
||||
<Image
|
||||
source={
|
||||
product.review.rate !== undefined
|
||||
? require(`../../../assets/images/icon_star_${product.review.rate}.png`)
|
||||
? require(`../../../assets/images/icon_star_5.png`)
|
||||
: require("../../../assets/images/icon_star_0.png")
|
||||
}
|
||||
style={styles.iconReviewRating}
|
||||
@@ -83,19 +92,18 @@ const ItemProduct = ({ product }: { product: any }) => {
|
||||
const styles = StyleSheet.create({
|
||||
productItem: {
|
||||
width: winWidth / 2 - 20,
|
||||
marginRight: 10,
|
||||
marginBottom: 10,
|
||||
padding: 12,
|
||||
padding: 10,
|
||||
borderWidth: 1,
|
||||
borderColor: "#d3d3d3",
|
||||
borderRadius: 8,
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
productImage: {
|
||||
width: winWidth / 2 - 20,
|
||||
width: winWidth / 2 - 44,
|
||||
height: 150,
|
||||
position: "relative",
|
||||
marginBottom: 5,
|
||||
borderWidth: 1,
|
||||
borderColor: "#d3d3d3",
|
||||
backgroundColor: "#fff",
|
||||
borderRadius: 8,
|
||||
},
|
||||
productImg: {
|
||||
width: "100%",
|
||||
@@ -189,7 +197,7 @@ const styles = StyleSheet.create({
|
||||
height: 18,
|
||||
},
|
||||
storeName: {
|
||||
fontSize: 13,
|
||||
fontSize: 12,
|
||||
fontWeight: "bold",
|
||||
color: "#000",
|
||||
},
|
||||
|
||||
115
src/components/product/ProductGallery.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import React, { useRef, useState, useCallback } from "react";
|
||||
import {
|
||||
View,
|
||||
Image,
|
||||
FlatList,
|
||||
TouchableOpacity,
|
||||
Dimensions,
|
||||
StyleSheet,
|
||||
} from "react-native";
|
||||
import Carousel from "react-native-reanimated-carousel";
|
||||
|
||||
const { width } = Dimensions.get("window");
|
||||
const THUMB_SIZE = 64;
|
||||
const SPACING = 10;
|
||||
|
||||
const images = [
|
||||
require("../../../assets/images/big-product-detail.png"),
|
||||
require("../../../assets/images/big-product-detail.jpg"),
|
||||
require("../../../assets/images/big-product-detail-2.jpg"),
|
||||
require("../../../assets/images/big-product-detail-3.jpg"),
|
||||
require("../../../assets/images/big-product-detail-4.jpg"),
|
||||
];
|
||||
|
||||
const ProductGallery = () => {
|
||||
const [activeIndex, setActiveIndex] = useState(0);
|
||||
const carouselRef = useRef<Carousel<any>>(null);
|
||||
const thumbnailListRef = useRef<FlatList>(null);
|
||||
|
||||
const scrollToThumbnail = useCallback((index: number) => {
|
||||
const offset = index * (THUMB_SIZE + SPACING) - width / 2 + THUMB_SIZE / 2;
|
||||
thumbnailListRef.current?.scrollToOffset({
|
||||
offset: Math.max(0, offset),
|
||||
animated: true,
|
||||
});
|
||||
}, []);
|
||||
|
||||
const onSnapToItem = useCallback(
|
||||
(index: number) => {
|
||||
setActiveIndex(index);
|
||||
scrollToThumbnail(index);
|
||||
},
|
||||
[scrollToThumbnail]
|
||||
);
|
||||
|
||||
const onThumbnailPress = useCallback((index: number) => {
|
||||
carouselRef.current?.scrollTo({ index, animated: true });
|
||||
}, []);
|
||||
|
||||
const renderThumbnail = useCallback(
|
||||
({ item, index }: { item: any; index: number }) => (
|
||||
<TouchableOpacity onPress={() => onThumbnailPress(index)}>
|
||||
<Image
|
||||
source={item}
|
||||
style={[
|
||||
styles.thumbnail,
|
||||
activeIndex === index && styles.activeThumbnail,
|
||||
]}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
),
|
||||
[activeIndex, onThumbnailPress]
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Carousel
|
||||
ref={carouselRef}
|
||||
loop={false}
|
||||
width={width}
|
||||
height={300}
|
||||
data={images}
|
||||
scrollAnimationDuration={400}
|
||||
renderItem={({ item }) => (
|
||||
<Image source={item} style={styles.bigImage} resizeMode="contain" />
|
||||
)}
|
||||
onSnapToItem={onSnapToItem}
|
||||
/>
|
||||
|
||||
<FlatList
|
||||
ref={thumbnailListRef}
|
||||
data={images}
|
||||
horizontal
|
||||
keyExtractor={(_, i) => i.toString()}
|
||||
renderItem={renderThumbnail}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
contentContainerStyle={styles.thumbList}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductGallery;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {},
|
||||
bigImage: {
|
||||
width: width - 40,
|
||||
height: 280,
|
||||
borderWidth: 1,
|
||||
borderColor: "#b1b1b1",
|
||||
borderRadius: 12,
|
||||
},
|
||||
thumbnail: {
|
||||
width: THUMB_SIZE,
|
||||
height: THUMB_SIZE,
|
||||
marginRight: SPACING,
|
||||
borderRadius: 6,
|
||||
borderWidth: 1,
|
||||
borderColor: "#b1b1b1",
|
||||
},
|
||||
activeThumbnail: {
|
||||
borderColor: "#1877F2",
|
||||
},
|
||||
thumbList: {},
|
||||
});
|
||||
98
src/components/product/ProductHTMLContent.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
LayoutChangeEvent,
|
||||
Dimensions,
|
||||
StyleSheet,
|
||||
} from "react-native";
|
||||
import RenderHTML from "react-native-render-html";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { LinearGradient } from "expo-linear-gradient";
|
||||
|
||||
const MAX_HEIGHT = 300;
|
||||
|
||||
const ProductHTMLContent = ({ htmlContent }: { htmlContent: string }) => {
|
||||
const [showFull, setShowFull] = useState(false);
|
||||
const [contentHeight, setContentHeight] = useState(0);
|
||||
const [shouldShowToggle, setShouldShowToggle] = useState(false);
|
||||
|
||||
const onContentLayout = (event: LayoutChangeEvent) => {
|
||||
const height = event.nativeEvent.layout.height;
|
||||
setContentHeight(height);
|
||||
if (height > MAX_HEIGHT) {
|
||||
setShouldShowToggle(true);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View
|
||||
style={[
|
||||
!showFull && shouldShowToggle
|
||||
? { maxHeight: MAX_HEIGHT, overflow: "hidden" }
|
||||
: null,
|
||||
]}
|
||||
onLayout={onContentLayout}
|
||||
>
|
||||
<RenderHTML
|
||||
contentWidth={Dimensions.get("window").width - 32}
|
||||
source={{ html: htmlContent }}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{!showFull && shouldShowToggle && (
|
||||
<LinearGradient
|
||||
colors={["transparent", "#ffffff"]}
|
||||
style={styles.fadeGradient}
|
||||
pointerEvents="none"
|
||||
/>
|
||||
)}
|
||||
|
||||
{shouldShowToggle && (
|
||||
<TouchableOpacity
|
||||
onPress={() => setShowFull(!showFull)}
|
||||
style={styles.button}
|
||||
>
|
||||
<Text style={styles.buttonText}>
|
||||
{showFull ? "Thu gọn" : "Xem thêm"}
|
||||
</Text>
|
||||
<Ionicons
|
||||
name={showFull ? "chevron-up-outline" : "chevron-down-outline"}
|
||||
size={18}
|
||||
color="#ff7a00"
|
||||
style={{ marginLeft: 4 }}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductHTMLContent;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: "#fff",
|
||||
position: "relative",
|
||||
},
|
||||
fadeGradient: {
|
||||
position: "absolute",
|
||||
bottom: 30,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: 80,
|
||||
zIndex: 1,
|
||||
},
|
||||
button: {
|
||||
marginTop: 12,
|
||||
alignSelf: "center",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
},
|
||||
buttonText: {
|
||||
color: "#ff7a00",
|
||||
fontSize: 14,
|
||||
},
|
||||
});
|
||||
178
src/components/product/SupplierItem.tsx
Normal file
@@ -0,0 +1,178 @@
|
||||
// components/SupplierItem.tsx
|
||||
import React from "react";
|
||||
import { View, Text, Image, TouchableOpacity, StyleSheet } from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
|
||||
interface SupplierItemProps {
|
||||
name: string;
|
||||
distance: string;
|
||||
rating: number;
|
||||
logo: any; // require('...') dùng để import hình ảnh cục bộ
|
||||
shippingPolicy: string;
|
||||
priceRange: string;
|
||||
hasVAT: boolean;
|
||||
products: string[];
|
||||
}
|
||||
|
||||
const SupplierItem: React.FC<SupplierItemProps> = ({
|
||||
name,
|
||||
distance,
|
||||
rating,
|
||||
logo,
|
||||
shippingPolicy,
|
||||
priceRange,
|
||||
hasVAT,
|
||||
products,
|
||||
}) => {
|
||||
return (
|
||||
<View style={styles.ItemSupplier}>
|
||||
{/* Logo + info */}
|
||||
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||
<View
|
||||
style={{
|
||||
marginRight: 10,
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
width: 50,
|
||||
height: 50,
|
||||
padding: 10,
|
||||
borderWidth: 1,
|
||||
borderColor: "#F3F3F3",
|
||||
borderRadius: 4,
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
source={logo}
|
||||
style={{ width: "100%", height: "100%", resizeMode: "contain" }}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
borderLeftWidth: 1,
|
||||
borderColor: "#b3b3b3",
|
||||
paddingLeft: 10,
|
||||
}}
|
||||
>
|
||||
<Text>
|
||||
<Ionicons name="star" size={14} color="#ff7a00" />
|
||||
<Ionicons name="star" size={14} color="#ff7a00" />
|
||||
<Ionicons name="star" size={14} color="#ff7a00" />
|
||||
<Ionicons name="star" size={14} color="#ff7a00" />
|
||||
<Ionicons name="star" size={14} color="#D9D9D9" />
|
||||
</Text>
|
||||
<Text style={{ color: "#1877F2", fontWeight: "bold" }}>{name}</Text>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "column",
|
||||
marginLeft: 10,
|
||||
borderLeftWidth: 1,
|
||||
borderColor: "#b3b3b3",
|
||||
paddingLeft: 10,
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
color: "#E85933",
|
||||
}}
|
||||
>
|
||||
Xem 7 cửa hàng
|
||||
</Text>
|
||||
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_map.png")}
|
||||
alt="icon store"
|
||||
style={{ width: 10 }}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
<Text style={{ marginLeft: 5 }}>3km</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Giá */}
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginBottom: 5,
|
||||
marginTop: 5,
|
||||
}}
|
||||
>
|
||||
<Text style={{ flexDirection: "row", alignItems: "center" }}>
|
||||
<Text>Giá: </Text>
|
||||
<Text style={{ color: "#D80A00", fontWeight: "bold" }}>
|
||||
{priceRange}
|
||||
</Text>
|
||||
</Text>
|
||||
{hasVAT && (
|
||||
<Text style={{ marginLeft: 10, fontWeight: "bold" }}>Đã có VAT</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Sản phẩm */}
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginBottom: 5,
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
{products.map((item, index) => (
|
||||
<Text
|
||||
key={index}
|
||||
style={{
|
||||
paddingRight: 10,
|
||||
borderRightWidth: index < products.length - 1 ? 1 : 0,
|
||||
borderColor: "#D9D9D9",
|
||||
marginRight: 10,
|
||||
}}
|
||||
>
|
||||
{item}
|
||||
</Text>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{/* Chính sách giao hàng */}
|
||||
<View style={{ flex: 1, marginBottom: 10 }}>
|
||||
<Text>{shippingPolicy}</Text>
|
||||
</View>
|
||||
|
||||
{/* Liên hệ */}
|
||||
<View
|
||||
style={{ flex: 1, justifyContent: "center", alignItems: "flex-end" }}
|
||||
>
|
||||
<TouchableOpacity
|
||||
style={{
|
||||
width: 130,
|
||||
height: 40,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
backgroundColor: "#F97316",
|
||||
borderRadius: 6,
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: "#fff", fontWeight: "500" }}>Liên hệ ngay</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupplierItem;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
ItemSupplier: {
|
||||
flex: 1,
|
||||
marginTop: 10,
|
||||
paddingBottom: 10,
|
||||
paddingTop: 10,
|
||||
borderBottomWidth: 1,
|
||||
borderColor: "#e3e3e3",
|
||||
},
|
||||
});
|
||||
171
src/components/product/itemProductSave.tsx
Normal file
@@ -0,0 +1,171 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
View,
|
||||
StyleSheet,
|
||||
Image,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
Dimensions,
|
||||
} from "react-native";
|
||||
import { globalStyles } from "../../styles/globalStyles";
|
||||
|
||||
var winWidth = Dimensions.get("window").width; //full width
|
||||
var winHeight = Dimensions.get("window").height;
|
||||
|
||||
const ItemProductSave = ({ product }: { product: any }) => {
|
||||
function formatCurrency(a: number | string): string {
|
||||
let b = parseFloat(a.toString())
|
||||
.toFixed(2)
|
||||
.replace(/(\d)(?=(\d{3})+\.)/g, "$1.")
|
||||
.toString();
|
||||
var len = b.length;
|
||||
b = b.substring(0, len - 3);
|
||||
return b;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.productItem}>
|
||||
<TouchableOpacity style={styles.productImage}>
|
||||
<Image
|
||||
source={{ uri: product.productImage.large }}
|
||||
style={styles.productImg}
|
||||
alt={product.productName}
|
||||
/>
|
||||
<View style={styles.iconSave}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_heart.png")}
|
||||
style={styles.imgsave}
|
||||
alt="icon-heart"
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<View>
|
||||
<TouchableOpacity>
|
||||
<Text numberOfLines={2} style={styles.productName}>
|
||||
{product.productName}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<View style={styles.BoxPriceRating}>
|
||||
<View style={globalStyles.boxFlex}>
|
||||
<Text style={styles.price}>{formatCurrency(product.price)}đ</Text>
|
||||
<Text style={styles.oldPrice}>
|
||||
{formatCurrency(product.oldPrice)}đ
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.boxStore}>
|
||||
<View style={styles.boxIconStore}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_store_white.png")}
|
||||
style={styles.iconStore}
|
||||
alt="icon store"
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</View>
|
||||
<Text style={styles.storeName}>
|
||||
Có {product.toltalStore} cửa hàng bán
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
productItem: {
|
||||
width: winWidth / 2 - 20,
|
||||
},
|
||||
productImage: {
|
||||
width: winWidth / 2 - 20,
|
||||
height: 200,
|
||||
position: "relative",
|
||||
marginBottom: 5,
|
||||
borderWidth: 1,
|
||||
borderColor: "#d3d3d3",
|
||||
backgroundColor: "#fff",
|
||||
borderRadius: 8,
|
||||
},
|
||||
productImg: {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "contain",
|
||||
},
|
||||
iconSave: {
|
||||
position: "absolute",
|
||||
right: 5,
|
||||
top: 5,
|
||||
width: 16,
|
||||
height: 13,
|
||||
zIndex: 9,
|
||||
},
|
||||
imgsave: {
|
||||
width: "100%",
|
||||
objectFit: "contain",
|
||||
margin: "auto",
|
||||
},
|
||||
productName: {
|
||||
fontWeight: 700,
|
||||
fontSize: 14,
|
||||
color: "#000",
|
||||
marginBottom: 5,
|
||||
},
|
||||
summary: {
|
||||
marginTop: 5,
|
||||
color: "#595959",
|
||||
},
|
||||
locahostPro: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
},
|
||||
iconMap: {},
|
||||
BoxPriceRating: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "flex-end",
|
||||
},
|
||||
price: {
|
||||
fontSize: 15,
|
||||
fontWeight: "bold",
|
||||
color: "#d80a00",
|
||||
marginRight: 10,
|
||||
},
|
||||
oldPrice: {
|
||||
fontSize: 13,
|
||||
textDecorationLine: "line-through",
|
||||
color: "#595959",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
iconReviewRating: {
|
||||
width: 58,
|
||||
height: 11,
|
||||
marginBottom: 2,
|
||||
},
|
||||
boxStore: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
marginTop: 10,
|
||||
},
|
||||
boxIconStore: {
|
||||
width: 24,
|
||||
height: 24,
|
||||
borderRadius: 25,
|
||||
backgroundColor: "#FF7A00",
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
marginRight: 5,
|
||||
},
|
||||
iconStore: {
|
||||
width: 18,
|
||||
height: 18,
|
||||
},
|
||||
storeName: {
|
||||
fontSize: 13,
|
||||
fontWeight: "bold",
|
||||
color: "#000",
|
||||
},
|
||||
});
|
||||
|
||||
export default ItemProductSave;
|
||||
@@ -39,4 +39,24 @@ export const categories = [
|
||||
name: "Pc văn phòng",
|
||||
image: "../../assets/images/category-pc.png",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: "Pc văn phòng",
|
||||
image: "../../assets/images/category-pc.png",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: "Pc văn phòng",
|
||||
image: "../../assets/images/category-pc.png",
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: "Pc văn phòng",
|
||||
image: "../../assets/images/category-pc.png",
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: "Pc văn phòng",
|
||||
image: "../../assets/images/category-pc.png",
|
||||
},
|
||||
];
|
||||
|
||||
41
src/layouts/AppLayout.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import React from "react";
|
||||
import { View, StyleSheet, ScrollView } from "react-native";
|
||||
import {
|
||||
useNavigation,
|
||||
NavigationProp,
|
||||
NavigationContainer,
|
||||
} from "@react-navigation/native";
|
||||
import Header from "../components/header/Header";
|
||||
import ButtonFooter from "../components/footer/ButtonFooter";
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
activeTab: string;
|
||||
};
|
||||
|
||||
const AppLayout = ({ children, activeTab }: Props) => {
|
||||
const navigation = useNavigation<NavigationProp<any>>();
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Header />
|
||||
<View style={styles.content}>{children}</View>
|
||||
<ButtonFooter navigation={navigation} activeTab={activeTab} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppLayout;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
maxWidth: 480,
|
||||
flex: 1,
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
@@ -3,17 +3,23 @@ import React from "react";
|
||||
import { createStackNavigator } from "@react-navigation/stack";
|
||||
import { NavigationContainer } from "@react-navigation/native";
|
||||
import HomeScreen from "../screens/HomeScreen";
|
||||
import ProductListBig from "../screens/product/ProductListBig";
|
||||
import ProductList from "../screens/product/ProductList";
|
||||
import ProductDetail from "../screens/product/ProductDetail";
|
||||
|
||||
const Stack = createStackNavigator();
|
||||
|
||||
const AppNavigator: React.FC = () => {
|
||||
return (
|
||||
<NavigationContainer>
|
||||
<Stack.Navigator initialRouteName="Home">
|
||||
<Stack.Screen name="Home" component={HomeScreen} />
|
||||
<Stack.Screen name="Product" />
|
||||
<Stack.Navigator
|
||||
initialRouteName="homepage"
|
||||
screenOptions={{ headerShown: false }}
|
||||
>
|
||||
<Stack.Screen name="homepage" component={HomeScreen} />
|
||||
<Stack.Screen name="productlist" component={ProductListBig} />
|
||||
<Stack.Screen name="productlistmain" component={ProductList} />
|
||||
<Stack.Screen name="productdetail" component={ProductDetail} />
|
||||
</Stack.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// src/screens/HomeScreen.tsx
|
||||
import React, { useState } from "react";
|
||||
import { useNavigation, NavigationProp } from "@react-navigation/native";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
@@ -16,21 +17,37 @@ import Swiper from "react-native-swiper";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { products } from "../data/product";
|
||||
import ProductItem from "../components/product/ItemProduct";
|
||||
import ProductItemSave from "../components/product/itemProductSave";
|
||||
import { categories } from "../data/category";
|
||||
import chunk from "lodash/chunk";
|
||||
import { globalAgent } from "http";
|
||||
import { WebView } from "react-native-webview";
|
||||
import AppLayout from "../layouts/AppLayout";
|
||||
import Footer from "../components/footer/Footer";
|
||||
|
||||
var winWidth = Dimensions.get("window").width; //full width
|
||||
var winHeight = Dimensions.get("window").height; //full height
|
||||
const ratio = winWidth / 930;
|
||||
const HomeScreen: React.FC = () => {
|
||||
const navigation = useNavigation<NavigationProp<any>>();
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<AppLayout activeTab="homepage">
|
||||
<ScrollView>
|
||||
<SliderHome />
|
||||
<BoxMenuHome />
|
||||
<BoxProductReviewTop />
|
||||
<BoxCategoryHome />
|
||||
<BoxBusiness />
|
||||
<BoxProductSaveHome />
|
||||
<BoxArticleBranch />
|
||||
<BoxArticleSale />
|
||||
<BoxArticleClassifieds />
|
||||
<BoxBannerSaleHome />
|
||||
<BoxPromotionHome />
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
</AppLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -64,28 +81,28 @@ const SliderHome = () => {
|
||||
<Image
|
||||
style={styles.imgSlider}
|
||||
source={require("../../assets/images/banner_slider.png")}
|
||||
resizeMode="contain"
|
||||
resizeMode="cover"
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.imgContainer}>
|
||||
<Image
|
||||
style={styles.imgSlider}
|
||||
source={require("../../assets/images/banner_slider.png")}
|
||||
resizeMode="contain"
|
||||
resizeMode="cover"
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.imgContainer}>
|
||||
<Image
|
||||
style={styles.imgSlider}
|
||||
source={require("../../assets/images/banner_slider.png")}
|
||||
resizeMode="contain"
|
||||
resizeMode="cover"
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.imgContainer}>
|
||||
<Image
|
||||
style={styles.imgSlider}
|
||||
source={require("../../assets/images/banner_slider.png")}
|
||||
resizeMode="contain"
|
||||
resizeMode="cover"
|
||||
/>
|
||||
</View>
|
||||
</Swiper>
|
||||
@@ -230,11 +247,30 @@ const BoxProductReviewTop = () => {
|
||||
};
|
||||
|
||||
const BoxCategoryHome = () => {
|
||||
const chunkedItems = chunk(categories, 8);
|
||||
|
||||
return (
|
||||
<View style={globalStyles.boxCategoryHome}>
|
||||
<Text style={globalStyles.textBoxCategoryHome}>Tìm theo danh mục</Text>
|
||||
<View style={globalStyles.listCategoryBox}>
|
||||
{categories.map((item) => (
|
||||
<Swiper
|
||||
style={globalStyles.listCategoryBox}
|
||||
loop={false}
|
||||
showsPagination={true}
|
||||
dot={<View style={globalStyles.dot} />}
|
||||
activeDot={<View style={globalStyles.activeDot} />}
|
||||
paginationStyle={{
|
||||
bottom: 10,
|
||||
}}
|
||||
>
|
||||
{chunkedItems.map((group, slideIndex) => (
|
||||
<View
|
||||
key={`slide-${slideIndex}`}
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
{group.map((item) => (
|
||||
<TouchableOpacity key={item.id} style={globalStyles.categoryItem}>
|
||||
<View style={globalStyles.boxImageCategory}>
|
||||
<Image
|
||||
@@ -246,6 +282,604 @@ const BoxCategoryHome = () => {
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
))}
|
||||
</Swiper>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const BoxBusiness = () => {
|
||||
return (
|
||||
<View style={globalStyles.BoxBusiness}>
|
||||
<Text style={globalStyles.textBoxBusiness}>DOANH NGHIỆP NỔI BẬT</Text>
|
||||
|
||||
<Swiper
|
||||
style={globalStyles.sliderBusinesses}
|
||||
autoplay={false}
|
||||
showsPagination={true}
|
||||
dot={<View style={globalStyles.dot} />}
|
||||
activeDot={<View style={globalStyles.activeDot} />}
|
||||
paginationStyle={{
|
||||
bottom: 10,
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
paddingHorizontal: 10,
|
||||
}}
|
||||
>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-hacom.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-hacom.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-anphat.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-gearvn.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
paddingHorizontal: 10,
|
||||
}}
|
||||
>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-hacom.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-hacom.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-anphat.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.logoItem}>
|
||||
<Image
|
||||
source={require("../../assets/images/logo-gearvn.png")}
|
||||
style={globalStyles.logoImage}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</Swiper>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const BoxProductSaveHome = () => {
|
||||
return (
|
||||
<View style={globalStyles.BoxProductSaveHome}>
|
||||
<Text style={globalStyles.textBoxProductSaveHome}>SẢN PHẨM ĐÃ LƯU</Text>
|
||||
|
||||
<View style={globalStyles.listProduct}>
|
||||
{products.map((item) => (
|
||||
<ProductItemSave key={item.id} product={item} />
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const BoxArticleBranch = () => {
|
||||
return (
|
||||
<View style={globalStyles.BoxArticleBranch}>
|
||||
<Text style={globalStyles.textBoxArticleBranche}>THÔNG TIN NGÀNH</Text>
|
||||
<View style={globalStyles.boxListArticle}>
|
||||
<View style={globalStyles.itemArticle}>
|
||||
<TouchableOpacity style={globalStyles.itemArticleImg}>
|
||||
<Image
|
||||
source={require("../../assets/images/image-article.png")}
|
||||
style={globalStyles.imgArticle}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={globalStyles.infoArticle}>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtName} numberOfLines={1}>
|
||||
Xu hướng công nghệ nhìn từ CES 2025
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtSummary} numberOfLines={2}>
|
||||
Loạt sản phẩm trưng bày tại CES 2025 cho thấy AI là xu hướng chính
|
||||
nhưng được...
|
||||
</Text>
|
||||
<View style={globalStyles.itemArtTime}>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons name="time" size={16} color="#5a5a5a" />
|
||||
<Text style={globalStyles.itemArtDate}>12/03/2025</Text>
|
||||
</View>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons
|
||||
name="link"
|
||||
size={16}
|
||||
style={{ marginLeft: 10 }}
|
||||
color="#5a5a5a"
|
||||
/>
|
||||
<Text style={globalStyles.itemArtSource}>
|
||||
Nguồn tin: vnexpress
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={globalStyles.itemArticle}>
|
||||
<TouchableOpacity style={globalStyles.itemArticleImg}>
|
||||
<Image
|
||||
source={require("../../assets/images/image-article.png")}
|
||||
style={globalStyles.imgArticle}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={globalStyles.infoArticle}>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtName} numberOfLines={1}>
|
||||
Xu hướng công nghệ nhìn từ CES 2025
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtSummary} numberOfLines={2}>
|
||||
Loạt sản phẩm trưng bày tại CES 2025 cho thấy AI là xu hướng chính
|
||||
nhưng được...
|
||||
</Text>
|
||||
<View style={globalStyles.itemArtTime}>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons name="time" size={16} color="#5a5a5a" />
|
||||
<Text style={globalStyles.itemArtDate}>12/03/2025</Text>
|
||||
</View>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons
|
||||
name="link"
|
||||
size={16}
|
||||
style={{ marginLeft: 10 }}
|
||||
color="#5a5a5a"
|
||||
/>
|
||||
<Text style={globalStyles.itemArtSource}>
|
||||
Nguồn tin: vnexpress
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={globalStyles.itemArticle}>
|
||||
<TouchableOpacity style={globalStyles.itemArticleImg}>
|
||||
<Image
|
||||
source={require("../../assets/images/image-article.png")}
|
||||
style={globalStyles.imgArticle}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={globalStyles.infoArticle}>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtName} numberOfLines={1}>
|
||||
Xu hướng công nghệ nhìn từ CES 2025
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtSummary} numberOfLines={2}>
|
||||
Loạt sản phẩm trưng bày tại CES 2025 cho thấy AI là xu hướng chính
|
||||
nhưng được...
|
||||
</Text>
|
||||
<View style={globalStyles.itemArtTime}>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons name="time" size={16} color="#5a5a5a" />
|
||||
<Text style={globalStyles.itemArtDate}>12/03/2025</Text>
|
||||
</View>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons
|
||||
name="link"
|
||||
size={16}
|
||||
style={{ marginLeft: 10 }}
|
||||
color="#5a5a5a"
|
||||
/>
|
||||
<Text style={globalStyles.itemArtSource}>
|
||||
Nguồn tin: vnexpress
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.btnMore}>Xem tất cả</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const BoxArticleSale = () => {
|
||||
return (
|
||||
<View style={globalStyles.BoxArticleBranch}>
|
||||
<Text style={globalStyles.textBoxArticleBranche}>
|
||||
THÔNG TIN khuyến mại
|
||||
</Text>
|
||||
<View style={globalStyles.boxListArticle}>
|
||||
<View style={globalStyles.itemArticle}>
|
||||
<TouchableOpacity style={globalStyles.itemArticleImg}>
|
||||
<Image
|
||||
source={require("../../assets/images/image-article.png")}
|
||||
style={globalStyles.imgArticle}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={globalStyles.infoArticle}>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtName} numberOfLines={1}>
|
||||
Xu hướng công nghệ nhìn từ CES 2025
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtSummary} numberOfLines={2}>
|
||||
Loạt sản phẩm trưng bày tại CES 2025 cho thấy AI là xu hướng chính
|
||||
nhưng được...
|
||||
</Text>
|
||||
<View style={globalStyles.itemArtTime}>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons name="time" size={16} color="#5a5a5a" />
|
||||
<Text style={globalStyles.itemArtDate}>12/03/2025</Text>
|
||||
</View>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons
|
||||
name="link"
|
||||
size={16}
|
||||
style={{ marginLeft: 10 }}
|
||||
color="#5a5a5a"
|
||||
/>
|
||||
<Text style={globalStyles.itemArtSource}>
|
||||
Nguồn tin: vnexpress
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={globalStyles.itemArticle}>
|
||||
<TouchableOpacity style={globalStyles.itemArticleImg}>
|
||||
<Image
|
||||
source={require("../../assets/images/image-article.png")}
|
||||
style={globalStyles.imgArticle}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={globalStyles.infoArticle}>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtName} numberOfLines={1}>
|
||||
Xu hướng công nghệ nhìn từ CES 2025
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtSummary} numberOfLines={2}>
|
||||
Loạt sản phẩm trưng bày tại CES 2025 cho thấy AI là xu hướng chính
|
||||
nhưng được...
|
||||
</Text>
|
||||
<View style={globalStyles.itemArtTime}>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons name="time" size={16} color="#5a5a5a" />
|
||||
<Text style={globalStyles.itemArtDate}>12/03/2025</Text>
|
||||
</View>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons
|
||||
name="link"
|
||||
size={16}
|
||||
style={{ marginLeft: 10 }}
|
||||
color="#5a5a5a"
|
||||
/>
|
||||
<Text style={globalStyles.itemArtSource}>
|
||||
Nguồn tin: vnexpress
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={globalStyles.itemArticle}>
|
||||
<TouchableOpacity style={globalStyles.itemArticleImg}>
|
||||
<Image
|
||||
source={require("../../assets/images/image-article.png")}
|
||||
style={globalStyles.imgArticle}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={globalStyles.infoArticle}>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtName} numberOfLines={1}>
|
||||
Xu hướng công nghệ nhìn từ CES 2025
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtSummary} numberOfLines={2}>
|
||||
Loạt sản phẩm trưng bày tại CES 2025 cho thấy AI là xu hướng chính
|
||||
nhưng được...
|
||||
</Text>
|
||||
<View style={globalStyles.itemArtTime}>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons name="time" size={16} color="#5a5a5a" />
|
||||
<Text style={globalStyles.itemArtDate}>12/03/2025</Text>
|
||||
</View>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons
|
||||
name="link"
|
||||
size={16}
|
||||
style={{ marginLeft: 10 }}
|
||||
color="#5a5a5a"
|
||||
/>
|
||||
<Text style={globalStyles.itemArtSource}>
|
||||
Nguồn tin: vnexpress
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.btnMore}>Xem tất cả</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const BoxArticleClassifieds = () => {
|
||||
return (
|
||||
<View style={globalStyles.BoxArticleBranch}>
|
||||
<Text style={globalStyles.textBoxArticleBranche}>THÔNG TIN rao vặt</Text>
|
||||
<View style={globalStyles.boxListArticle}>
|
||||
<View style={globalStyles.itemArticle}>
|
||||
<TouchableOpacity style={globalStyles.itemArticleImg}>
|
||||
<Image
|
||||
source={require("../../assets/images/image-article.png")}
|
||||
style={globalStyles.imgArticle}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={globalStyles.infoArticle}>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtName} numberOfLines={1}>
|
||||
Mac air màu xám 256GB like new
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtSummary} numberOfLines={1}>
|
||||
Intel Core i5 / 8GB / 256GB / SSD
|
||||
</Text>
|
||||
<Text style={globalStyles.itemArtPrice}>19.999.000đ</Text>
|
||||
<View style={globalStyles.itemArtlocal}>
|
||||
<Ionicons name="location-sharp" size={16} color="#5a5a5a" />
|
||||
<Text style={globalStyles.textArtlocal}>Quận thanh xuân</Text>
|
||||
</View>
|
||||
<View style={globalStyles.itemArtUploadtime}>
|
||||
<Ionicons
|
||||
name="time"
|
||||
size={16}
|
||||
style={{ marginRight: 3 }}
|
||||
color="#5a5a5a"
|
||||
/>
|
||||
<Text>30 phút trước </Text>
|
||||
<Text>|</Text>
|
||||
<Text> Còn 05 ngày</Text>
|
||||
</View>
|
||||
<View style={globalStyles.itemArtUser}>
|
||||
<Image
|
||||
source={require("../../assets/images/avartar.png")}
|
||||
style={globalStyles.imgAvatar}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
<Text style={globalStyles.itemArtNameUser}>Thanh mai</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={globalStyles.itemArticle}>
|
||||
<TouchableOpacity style={globalStyles.itemArticleImg}>
|
||||
<Image
|
||||
source={require("../../assets/images/image-article.png")}
|
||||
style={globalStyles.imgArticle}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<View style={globalStyles.infoArticle}>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtName} numberOfLines={1}>
|
||||
Mac air màu xám 256GB like new
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={globalStyles.itemArtSummary} numberOfLines={1}>
|
||||
Intel Core i5 / 8GB / 256GB / SSD
|
||||
</Text>
|
||||
<Text style={globalStyles.itemArtPrice}>19.999.000đ</Text>
|
||||
<View style={globalStyles.itemArtlocal}>
|
||||
<Ionicons name="location-sharp" size={16} color="#5a5a5a" />
|
||||
<Text style={globalStyles.textArtlocal}>Quận thanh xuân</Text>
|
||||
</View>
|
||||
<View style={globalStyles.itemArtUploadtime}>
|
||||
<Ionicons
|
||||
name="time"
|
||||
size={16}
|
||||
style={{ marginRight: 3 }}
|
||||
color="#5a5a5a"
|
||||
/>
|
||||
<Text>30 phút trước </Text>
|
||||
<Text>|</Text>
|
||||
<Text> Còn 05 ngày</Text>
|
||||
</View>
|
||||
<View style={globalStyles.itemArtUser}>
|
||||
<Image
|
||||
source={require("../../assets/images/avartar.png")}
|
||||
style={globalStyles.imgAvatar}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
<Text style={globalStyles.itemArtNameUser}>Thanh mai</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<TouchableOpacity>
|
||||
<Text style={globalStyles.btnMore}>Xem tất cả</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const BoxBannerSaleHome = () => {
|
||||
return (
|
||||
<View style={globalStyles.BoxBannerSaleHome}>
|
||||
<Swiper
|
||||
style={globalStyles.sliderBannerSale}
|
||||
autoplay={false}
|
||||
showsPagination={true}
|
||||
dot={<View style={globalStyles.dot} />}
|
||||
activeDot={<View style={globalStyles.activeDot} />}
|
||||
paginationStyle={{
|
||||
bottom: 10,
|
||||
}}
|
||||
>
|
||||
<View style={{ flexDirection: "row" }}>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-1.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-2.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={{ flexDirection: "row" }}>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-2.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-3.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={{ flexDirection: "row" }}>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-3.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.itemBannerSale}>
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-1.png")}
|
||||
style={globalStyles.imgBannerSale}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</Swiper>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const BoxPromotionHome = () => {
|
||||
const [showVideo, setShowVideo] = useState(false);
|
||||
|
||||
const videoId = "LcQBXGLWX8I";
|
||||
const embedUrl = `https://www.youtube.com/embed/${videoId}?autoplay=1`;
|
||||
|
||||
return (
|
||||
<View style={globalStyles.BoxPromotionHome}>
|
||||
<Text style={globalStyles.textBoxArticleBranche}>Sự kiện</Text>
|
||||
<Text style={globalStyles.textBoxArticleBranche}>
|
||||
và chương trình khuyến mãi
|
||||
</Text>
|
||||
<View style={globalStyles.containerVideo}>
|
||||
{showVideo ? (
|
||||
<WebView
|
||||
source={{ uri: embedUrl }}
|
||||
style={globalStyles.boxVideo}
|
||||
allowsFullscreenVideo
|
||||
/>
|
||||
) : (
|
||||
<TouchableOpacity
|
||||
onPress={() => setShowVideo(true)}
|
||||
style={globalStyles.touchArea}
|
||||
>
|
||||
<View style={globalStyles.overlay} />
|
||||
<Image
|
||||
source={require("../../assets/images/banner-sale-2.png")}
|
||||
style={globalStyles.imageYoutobe}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
<Ionicons
|
||||
name="logo-youtube"
|
||||
size={34}
|
||||
color="red"
|
||||
style={globalStyles.iconPlay}
|
||||
/>
|
||||
<View style={globalStyles.infoVideo}>
|
||||
<View style={globalStyles.flex}>
|
||||
<Ionicons name="time-outline" size={20} color="white" />
|
||||
<Text style={{ color: "#fff", marginLeft: 5 }}>
|
||||
10pm 25/02/2025
|
||||
</Text>
|
||||
</View>
|
||||
<Text style={{ color: "#fff", marginTop: 4, fontWeight: 700 }}>
|
||||
Showroom laptop 2025 tại Hà Nội{" "}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={globalStyles.listEvenBanner}>
|
||||
<TouchableOpacity style={globalStyles.itemEven}>
|
||||
<Image
|
||||
source={require("../../assets/images/promotions-1.png")}
|
||||
style={globalStyles.imgEven}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.itemEven}>
|
||||
<Image
|
||||
source={require("../../assets/images/promotions-2.png")}
|
||||
style={globalStyles.imgEven}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.itemEven}>
|
||||
<Image
|
||||
source={require("../../assets/images/promotions-3.png")}
|
||||
style={globalStyles.imgEven}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={globalStyles.itemEven}>
|
||||
<Image
|
||||
source={require("../../assets/images/promotions-4.png")}
|
||||
style={globalStyles.imgEven}
|
||||
alt="anh tin tuc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -253,33 +887,33 @@ const BoxCategoryHome = () => {
|
||||
export default HomeScreen;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
homePage: {
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
slider: {
|
||||
width: winWidth,
|
||||
padding: 10,
|
||||
width: winWidth - 20,
|
||||
overflow: "hidden",
|
||||
borderRadius: 10,
|
||||
height: ratio * 430,
|
||||
margin: 10,
|
||||
},
|
||||
sliderSwipper: {
|
||||
height: 210,
|
||||
width: "100%",
|
||||
overflow: "hidden",
|
||||
borderRadius: 10,
|
||||
},
|
||||
imgContainer: {
|
||||
width: winWidth,
|
||||
height: 220,
|
||||
width: "100%",
|
||||
borderRadius: 10,
|
||||
overflow: "hidden",
|
||||
objectFit: "cover",
|
||||
},
|
||||
imgSlider: {
|
||||
width: winWidth,
|
||||
height: "100%",
|
||||
objectFit: "cover",
|
||||
overflow: "hidden",
|
||||
borderRadius: 10,
|
||||
},
|
||||
buttonNext: {
|
||||
color: "#fff", // Màu chữ cho các nút chuyển
|
||||
|
||||
446
src/screens/product/BoxReview.tsx
Normal file
@@ -0,0 +1,446 @@
|
||||
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>
|
||||
<View style={styles.BoxReview}>
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.headerTitle}>Thành viên BestPC đánh giá</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.content}>
|
||||
{/* Left */}
|
||||
<View style={styles.left}>
|
||||
<Text style={styles.totalReview}>54 đánh giá</Text>
|
||||
<View style={styles.ratingRow}>
|
||||
<Text style={styles.star}>
|
||||
<Ionicons name="star" size={20} color="#ff7a00" />
|
||||
<Ionicons name="star" size={20} color="#ff7a00" />
|
||||
<Ionicons name="star" size={20} color="#ff7a00" />
|
||||
<Ionicons name="star" size={20} color="#ff7a00" />
|
||||
<Ionicons name="star" size={20} color="#d9d9d9" />
|
||||
</Text>
|
||||
<Text style={styles.ratingText}>4.8</Text>
|
||||
</View>
|
||||
|
||||
{/* Rating breakdown */}
|
||||
<View style={styles.ratingBreakdown}>
|
||||
{[5, 4, 3, 2, 1].map((star) => (
|
||||
<View key={star} style={styles.ratingLine}>
|
||||
{renderStars(star)}
|
||||
<Text>{50} đánh giá</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{/* Button */}
|
||||
<View style={styles.reviewBtnArea}>
|
||||
<Text style={styles.reviewPrompt}>
|
||||
Đánh giá của bạn về sản phẩm
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={styles.reviewBtn}
|
||||
onPress={() => setShowReviewModal(true)}
|
||||
>
|
||||
<Text style={styles.reviewBtnText}>Gửi đánh giá của bạn</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 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>
|
||||
<View style={styles.BoxReview}>
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.headerTitle}>Đánh giá trên internet</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.content}>
|
||||
{/* Left */}
|
||||
<View style={styles.left}>
|
||||
<Text style={styles.totalReview}>54 đánh giá</Text>
|
||||
<View style={styles.ratingRow}>
|
||||
<Text style={styles.star}>
|
||||
<Ionicons name="star" size={20} color="#ff7a00" />
|
||||
<Ionicons name="star" size={20} color="#ff7a00" />
|
||||
<Ionicons name="star" size={20} color="#ff7a00" />
|
||||
<Ionicons name="star" size={20} color="#ff7a00" />
|
||||
<Ionicons name="star" size={20} color="#d9d9d9" />
|
||||
</Text>
|
||||
<Text style={styles.ratingText}>4.8</Text>
|
||||
</View>
|
||||
|
||||
{/* Rating breakdown */}
|
||||
<View style={styles.ratingBreakdown}>
|
||||
{[5, 4, 3, 2, 1].map((star) => (
|
||||
<View key={star} style={styles.ratingLine}>
|
||||
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||
<Text>Hanoicomputer</Text>
|
||||
<Text style={{ marginLeft: 5, color: "#1877f2" }}>
|
||||
({50})
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{renderStars(star)}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{/* Button */}
|
||||
<View style={styles.reviewBtnArea}>
|
||||
<Text style={styles.reviewPrompt}>
|
||||
Đánh giá của bạn về sản phẩm
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={styles.reviewBtn}
|
||||
onPress={() => setShowReviewModal(true)}
|
||||
>
|
||||
<Text style={styles.reviewBtnText}>Gửi đánh giá của bạn</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Right */}
|
||||
<View style={styles.right}>
|
||||
<FlatList
|
||||
data={reviews}
|
||||
keyExtractor={(item) => item.id}
|
||||
renderItem={({ item }) => (
|
||||
<View style={styles.reviewItem}>
|
||||
<View style={styles.avatarBox}>
|
||||
<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>
|
||||
<TouchableOpacity
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Text style={{ marginRight: 5 }}>Xem link nguồn</Text>
|
||||
<Ionicons name="share-social" size={24} color="black" />
|
||||
</TouchableOpacity>
|
||||
</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>
|
||||
<ReviewModal
|
||||
visible={showReviewModal}
|
||||
onClose={() => setShowReviewModal(false)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
BoxReview: {
|
||||
padding: 15,
|
||||
backgroundColor: "#fff",
|
||||
marginTop: 20,
|
||||
borderRadius: 8,
|
||||
},
|
||||
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;
|
||||
364
src/screens/product/ProductDetail.tsx
Normal file
@@ -0,0 +1,364 @@
|
||||
import React, { useState } from "react";
|
||||
import { useNavigation, NavigationProp } from "@react-navigation/native";
|
||||
import AppLayout from "@layouts/AppLayout";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
Image,
|
||||
FlatList,
|
||||
TouchableOpacity,
|
||||
ScrollView,
|
||||
Dimensions,
|
||||
} from "react-native";
|
||||
import { globalStyles } from "styles/globalStyles";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import Feather from "@expo/vector-icons/Feather";
|
||||
|
||||
import Swiper from "react-native-swiper";
|
||||
const { width } = Dimensions.get("window");
|
||||
import ProductGallery from "@components/product/ProductGallery";
|
||||
import SupplierList from "./SupplierList";
|
||||
import ReviewSection from "./BoxReview";
|
||||
import ProductInformation from "./ProductInformation";
|
||||
import ProductSpecification from "./ProductSpecification";
|
||||
import { products } from "../../data/product";
|
||||
import ProductItem from "@components/product/ItemProduct";
|
||||
import Footer from "@components/footer/Footer";
|
||||
|
||||
const ProductDetail = () => {
|
||||
const navigation = useNavigation<NavigationProp<any>>();
|
||||
|
||||
return (
|
||||
<AppLayout activeTab="productdetail">
|
||||
<ScrollView>
|
||||
<View style={styles.container}>
|
||||
{/* Breadcrumb */}
|
||||
<View style={globalStyles.breadcrumb}>
|
||||
<TouchableOpacity
|
||||
style={globalStyles.breadcrumbItem}
|
||||
onPress={() => navigation.navigate("homepage" as never)}
|
||||
>
|
||||
<Ionicons name="home-outline" size={20} color="#637381" />
|
||||
</TouchableOpacity>
|
||||
<Ionicons name="chevron-forward-outline" size={14} color="#999" />
|
||||
<Text style={[globalStyles.breadcrumbText, { fontWeight: "600" }]}>
|
||||
Màn hình máy tính
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
padding: 10,
|
||||
backgroundColor: "#fff",
|
||||
marginTop: 15,
|
||||
borderRadius: 4,
|
||||
}}
|
||||
>
|
||||
<View style={styles.top}>
|
||||
<ProductGallery />
|
||||
</View>
|
||||
<View style={styles.bottom}>
|
||||
<Text style={styles.productTitle}>
|
||||
Laptop Gaming Asus TUF FX505GE-BQ037T Core i7-8750H/Win10(15.6"
|
||||
FHD) - Hàng Chính Hãng
|
||||
</Text>
|
||||
|
||||
<View style={styles.row}>
|
||||
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||
<Ionicons
|
||||
name="star"
|
||||
style={{ marginRight: 3, paddingTop: 3 }}
|
||||
size={15}
|
||||
color="#ff7a00"
|
||||
/>
|
||||
<Text style={styles.review}>5/5</Text>
|
||||
</View>
|
||||
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||
<Ionicons
|
||||
name="eye-outline"
|
||||
style={{ marginRight: 3 }}
|
||||
size={15}
|
||||
color="black"
|
||||
/>
|
||||
<Text style={styles.view}>120</Text>
|
||||
</View>
|
||||
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||
<Ionicons
|
||||
name="time-outline"
|
||||
style={{ marginRight: 3 }}
|
||||
size={15}
|
||||
color="black"
|
||||
/>
|
||||
<Text style={styles.date}>12/03/2025</Text>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
style={{ flexDirection: "row", alignItems: "center" }}
|
||||
>
|
||||
<Ionicons
|
||||
style={{ marginRight: 3 }}
|
||||
name="share-social-outline"
|
||||
size={15}
|
||||
color="black"
|
||||
/>
|
||||
<Text style={styles.share}> Chia sẻ</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<View style={styles.row}>
|
||||
<Text style={{ fontSize: 13 }}>
|
||||
Reviews trên: <Text style={styles.link}>Internet</Text> - 1233
|
||||
đánh giá
|
||||
</Text>
|
||||
<Text style={{ fontSize: 13 }}>
|
||||
| <Text style={styles.link}>BestPC</Text> - 12003 đánh giá
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.priceBox}>
|
||||
<Text style={styles.priceLabel}>Giá: </Text>
|
||||
<Text style={styles.price}>9.000.000đ - 12.000.000đ</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.boxStore}>
|
||||
<View style={styles.boxIconStore}>
|
||||
<Image
|
||||
source={require("../../../assets/images/icon_store_white.png")}
|
||||
style={styles.iconStore}
|
||||
alt="icon store"
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</View>
|
||||
<Text style={styles.storeName}>Có 12 cửa hàng bán</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.summaryBox}>
|
||||
<Text>
|
||||
• CPU: Intel Core i7-8750H (2.2GHz - 4.1GHz / 9MB / 6 nhân, 12
|
||||
luồng)
|
||||
</Text>
|
||||
<Text>• Màn hình: 15.6" (1920 x 1080), không cảm ứng</Text>
|
||||
<Text>• RAM: 1 x 8GB DDR4 2666MHz</Text>
|
||||
<Text>• GPU: Intel UHD 630 / NVIDIA GTX 1050Ti 4GB</Text>
|
||||
<Text>• Lưu trữ: 128GB SSD M.2 NVMe / 1TB HDD</Text>
|
||||
<Text>• OS: Windows 10 Home SL 64-bit</Text>
|
||||
<Text>• Pin: 4 cell 64Wh, liền</Text>
|
||||
<Text>• Nặng: 2.5kg</Text>
|
||||
<Text>• Cổng: 1x USB 2.0,...</Text>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity style={styles.saveButton}>
|
||||
<Feather name="file-plus" size={24} color="black" />
|
||||
<Text style={styles.saveText}>Lưu sản phẩm lại xem sau</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* nhà cung cấp */}
|
||||
<SupplierList />
|
||||
|
||||
{/* đánh giá */}
|
||||
<ReviewSection />
|
||||
|
||||
{/* mô tả sản phẩm */}
|
||||
<ProductInformation />
|
||||
{/* thông số sản phẩm */}
|
||||
<ProductSpecification />
|
||||
{/* sản phẩm tương tự */}
|
||||
<View style={styles.BoxSimilarProduct}>
|
||||
<Text style={styles.textSimilarProduct}>Sản phẩm tương tự</Text>
|
||||
<View style={styles.listProductSimilar}>
|
||||
{products.map((item) => (
|
||||
<ProductItem key={item.id} product={item} />
|
||||
))}
|
||||
</View>
|
||||
<TouchableOpacity style={{ marginTop: 10, marginBottom: 10 }}>
|
||||
<Text style={globalStyles.moreAll}>Xem tất cả</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* sản phẩm bạn thích */}
|
||||
<View style={styles.BoxLikeProduct}>
|
||||
<Text style={styles.textLikeProduct}>
|
||||
Sản phẩm có thể bạn thích
|
||||
</Text>
|
||||
<View style={styles.listProductLike}>
|
||||
{products.map((item) => (
|
||||
<ProductItem key={item.id} product={item} />
|
||||
))}
|
||||
</View>
|
||||
<TouchableOpacity style={{ marginTop: 10, marginBottom: 10 }}>
|
||||
<Text style={globalStyles.moreAll}>Xem tất cả</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductDetail;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 10,
|
||||
backgroundColor: "#efefef",
|
||||
paddingBottom: 10,
|
||||
},
|
||||
top: {},
|
||||
bigSwiper: {
|
||||
height: 250,
|
||||
},
|
||||
slide: {
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
height: 250,
|
||||
},
|
||||
bigImage: {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
},
|
||||
thumbnailWrapper: {
|
||||
marginTop: 12,
|
||||
flexDirection: "row",
|
||||
},
|
||||
thumbItem: {
|
||||
marginRight: 10,
|
||||
},
|
||||
thumbImage: {
|
||||
width: 60,
|
||||
height: 60,
|
||||
borderWidth: 1,
|
||||
borderColor: "#ccc",
|
||||
borderRadius: 8,
|
||||
},
|
||||
bottom: {
|
||||
marginTop: 20,
|
||||
},
|
||||
productTitle: {
|
||||
fontSize: 16,
|
||||
fontWeight: "bold",
|
||||
color: "#000",
|
||||
marginBottom: 10,
|
||||
},
|
||||
row: {
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
marginBottom: 5,
|
||||
gap: 10,
|
||||
},
|
||||
review: { marginRight: 10 },
|
||||
view: { marginRight: 10, color: "#1877f2" },
|
||||
date: { marginRight: 10 },
|
||||
share: {},
|
||||
link: {
|
||||
color: "#1877F2",
|
||||
fontWeight: "600",
|
||||
},
|
||||
priceBox: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginVertical: 10,
|
||||
},
|
||||
priceLabel: { fontSize: 16 },
|
||||
price: {
|
||||
fontSize: 24,
|
||||
color: "#D80A00",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
storeBox: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginBottom: 10,
|
||||
},
|
||||
summaryBox: {
|
||||
marginTop: 10,
|
||||
},
|
||||
saveButton: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginTop: 15,
|
||||
padding: 10,
|
||||
borderWidth: 1,
|
||||
borderColor: "#D3D3D3",
|
||||
borderRadius: 4,
|
||||
justifyContent: "center",
|
||||
},
|
||||
saveIcon: {
|
||||
width: 18,
|
||||
height: 24,
|
||||
marginRight: 10,
|
||||
},
|
||||
saveText: {
|
||||
fontSize: 16,
|
||||
fontWeight: "600",
|
||||
},
|
||||
boxStore: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginTop: 5,
|
||||
},
|
||||
boxIconStore: {
|
||||
width: 24,
|
||||
height: 24,
|
||||
borderRadius: 25,
|
||||
backgroundColor: "#FF7A00",
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
marginRight: 5,
|
||||
},
|
||||
iconStore: {
|
||||
width: 18,
|
||||
height: 18,
|
||||
},
|
||||
storeName: {
|
||||
fontSize: 14,
|
||||
fontWeight: 400,
|
||||
color: "#000",
|
||||
},
|
||||
BoxSimilarProduct: {
|
||||
backgroundColor: "#fff",
|
||||
marginTop: 15,
|
||||
borderRadius: 8,
|
||||
},
|
||||
textSimilarProduct: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#B1B1B1",
|
||||
padding: 10,
|
||||
fontSize: 16,
|
||||
fontWeight: "bold",
|
||||
},
|
||||
listProductSimilar: {
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
gap: 5,
|
||||
marginLeft: 7,
|
||||
marginTop: 10,
|
||||
},
|
||||
BoxLikeProduct: {
|
||||
backgroundColor: "#fff",
|
||||
marginTop: 15,
|
||||
borderRadius: 8,
|
||||
},
|
||||
textLikeProduct: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#B1B1B1",
|
||||
padding: 10,
|
||||
fontSize: 16,
|
||||
fontWeight: "bold",
|
||||
},
|
||||
listProductLike: {
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
gap: 5,
|
||||
marginLeft: 7,
|
||||
marginTop: 10,
|
||||
},
|
||||
});
|
||||
252
src/screens/product/ProductInformation.tsx
Normal file
@@ -0,0 +1,252 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
ScrollView,
|
||||
Image,
|
||||
TouchableOpacity,
|
||||
StyleSheet,
|
||||
} from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
|
||||
import ProductHTMLContent from "@components/product/ProductHTMLContent";
|
||||
|
||||
const productHtml = `
|
||||
<p style="text-align: justify;"><strong>Laptop HP Victus 16 R0376TX AY8Z2PA
|
||||
</strong> sở
|
||||
hữu chip xử lý Intel Core i7
|
||||
13700HX cùng VGA RTX 3050 6GB để có được trải nghiệm chơi game, làm việc hiệu
|
||||
quả.
|
||||
Mẫu <a href="https://cellphones.com.vn/laptop/hp/victus.html" title="HP Victus"
|
||||
target="_blank"><strong>HP
|
||||
Victus</strong></a> này còn được trang bị màn hình 16 inch FHD 165Hz
|
||||
giúp
|
||||
tái tạo hình ảnh sắc nét, mượt mà.
|
||||
Kèm theo đó là thiết kế bền bỉ, hiện đại để có thể sử dụng ở nhiều không gian.
|
||||
</p>
|
||||
|
||||
<h2 style="scroll-margin : 154px;"
|
||||
id="laptop-hp-victus-16-r0376tx-ay8z2pa-hieu-nang-manh-me-hien-thi-an-tuong">
|
||||
<strong>
|
||||
Laptop HP Victus 16 R0376TX AY8Z2PA - Hiệu năng mạnh mẽ, hiển thị ấn tượng
|
||||
</strong>
|
||||
</h2>
|
||||
<p style="text-align: justify;">HP Victus 16 R0376TX AY8Z2PA với bộ vi xử lý và card
|
||||
đồ
|
||||
họa rời mạnh mẽ sẽ mang tới trải
|
||||
nghiệm chơi game, làm việc mượt mà, hiệu quả. Hãy cùng tìm hiểu thêm những điểm
|
||||
nổi
|
||||
bật mà mẫu laptop gaming của
|
||||
<strong> HP Victus </strong> này sở hữu trong bài viết sau.
|
||||
</p>
|
||||
<h3 style="scroll-margin : 154px;"
|
||||
id="nang-cao-hieu-suat-xu-ly-voi-chip-core-i7-13700hx"><strong> Nâng cao hiệu
|
||||
suất
|
||||
xử
|
||||
lý với chip Core i7 13700HX</strong></h3>
|
||||
<p style="text-align: justify;">Laptop HP Victus 16 R0376TX AY8Z2PA được trang bị
|
||||
con
|
||||
chip xử lý Core i7 13700HX của
|
||||
Intel. Con chip Core i7 16 lõi, 24 luồng này sở hữu khả năng ép xung cực đại lên
|
||||
tới
|
||||
5GHz để luôn có thể xử lý dữ
|
||||
liệu trong thời gian ngắn. Với bộ nhớ đệm 30MB, hiệu suất xử lý các tác vụ phức
|
||||
tạp
|
||||
của laptop sẽ được giảm đi đáng
|
||||
kể.</p>
|
||||
<p style="text-align: justify;"><img
|
||||
src="https://cdn2.cellphones.com.vn/insecure/rs:fill:0:0/q:90/plain/https://cellphones.com.vn/media/wysiwyg/laptop/HP/Victus/Laptop-hp-victus-16-r0376tx-ay8z2pa-1.jpg"
|
||||
alt="Cấu hình laptop HP Victus 16 R0376TX AY8Z2PA" loading="lazy"></p>
|
||||
<p style="text-align: justify;">Để nâng cao khả năng xử lý đồ hoạ, HP còn trang bị
|
||||
cho
|
||||
phiên bản <a href="https://cellphones.com.vn/laptop/hp/victus/victus-16.html"
|
||||
title="laptop Victus 16" target="_blank"><strong>laptop Victus
|
||||
16</strong></a>
|
||||
này card đồ hoạ rời NVIDIA GeForce RTX 3050 6GB GDDR6. Nhờ
|
||||
vậy mà người dùng có thể tự tin trải nghiệm các tựa game với mức cấu hình cao.
|
||||
Không
|
||||
dừng ở đó, các nhu cầu chỉnh
|
||||
sửa hình ảnh, dựng phim, tạo hình 3D,...chuyên nghiệp cũng được thực hiện mượt
|
||||
mà.
|
||||
</p>
|
||||
<h3 style="scroll-margin : 154px;"
|
||||
id="tich-hop-o-cung-toc-do-cao-cung-dung-luong-ram-lon"><strong> Tích hợp ổ cứng
|
||||
tốc
|
||||
độ cao cùng dung lượng RAM lớn </strong></h3>
|
||||
<p style="text-align: justify;">HP Victus 16 R0376TX AY8Z2PA được trang bị sẵn 2
|
||||
thanh
|
||||
RAM chuẩn DDR5 có tốc độ bus lên
|
||||
tới 4800MT/s. Với tổng dung lượng RAM 16GB, mẫu laptop gaming HP này sẽ đáp ứng
|
||||
tốt
|
||||
nhu cầu đa nhiệm. Không chỉ các
|
||||
tác vụ cơ bản mà nhu cầu đa nhiệm nâng cao trong công việc cũng sẽ được thực
|
||||
hiện
|
||||
mượt mà mà không cần phải nâng cấp
|
||||
cấu hình. Ngoài ra, laptop HP Victus 16 R0376TX AY8Z2PA còn sở hữu một ổ cứng
|
||||
SSD
|
||||
tốc độ cao có dung lượng
|
||||
512GB. </p>
|
||||
<p style="text-align: justify;"><img
|
||||
src="https://cdn2.cellphones.com.vn/insecure/rs:fill:0:0/q:90/plain/https://cellphones.com.vn/media/wysiwyg/laptop/HP/Victus/Laptop-hp-victus-16-r0376tx-ay8z2pa-2.jpg"
|
||||
alt="Cấu hình laptop HP Victus 16 R0376TX AY8Z2PA" loading="lazy"></p>
|
||||
<h3 style="scroll-margin : 154px;" id="thiet-ke-hien-dai-ben-bi"><strong> Thiết kế
|
||||
hiện
|
||||
đại, bền bỉ </strong></h3>
|
||||
<p style="text-align: justify;">Laptop Victus 16 R0376TX AY8Z2PA được HP thiết kế
|
||||
hướng
|
||||
tới phong cách hiện đại, tối
|
||||
giản. Tuy vậy nhưng sản phẩm vẫn mang đậm dấu ấn gaming với tông màu đen thu hút
|
||||
và
|
||||
mạnh mẽ. Kèm theo đó là một tổng
|
||||
thể chắc chắn, bền bỉ cùng phần bản lề kích thước lớn.</p>
|
||||
<p style="text-align: justify;">Với trọng lượng khoảng 2.31kg, người dùng vẫn có thể
|
||||
tiện lợi mang theo phiên bản laptop
|
||||
HP Victus này mà không gặp bất tiện. So với các mẫu laptop gaming khác, đây được
|
||||
coi
|
||||
là một điểm cộng giúp sản phẩm
|
||||
đáp ứng nhu cầu chơi game ở nhiều không gian của người dùng.</p>
|
||||
<p style="text-align: justify;"><img
|
||||
src="https://cdn2.cellphones.com.vn/insecure/rs:fill:0:0/q:90/plain/https://cellphones.com.vn/media/wysiwyg/laptop/HP/Victus/Laptop-hp-victus-16-r0376tx-ay8z2pa-3.jpg"
|
||||
alt="Thiết kế laptop HP Victus 16 R0376TX AY8Z2PA" loading="lazy"></p>
|
||||
<p style="text-align: justify;">Để hỗ trợ tốt cả nhu cầu chơi game và làm việc, HP
|
||||
đã
|
||||
trang bị cho laptop Victus 16
|
||||
R0376TX AY8Z2PA bộ bàn phím Full-size. Với phần bàn phím số riêng biệt, người
|
||||
dùng
|
||||
sẽ cải thiện được tốc độ nhập
|
||||
liệu trong khi làm việc. Bàn phím của laptop còn được tích hợp hệ thống đèn nền
|
||||
RGB
|
||||
1 để hỗ trợ việc gõ phím trong
|
||||
điều kiện thiếu sáng.</p>
|
||||
<h3 style="scroll-margin : 154px;" id="hien-thi-sac-net-va-muot-ma"><strong> Hiển
|
||||
thị
|
||||
sắc nét và mượt mà </strong></h3>
|
||||
<p style="text-align: justify;">Laptop HP Victus 16 R0376TX AY8Z2PA sở hữu không
|
||||
giản
|
||||
hiển thị cực lớn khi được trang bị
|
||||
màn hình có kích thước 16.1 inch. Kèm theo đó là độ phân giải FHD (1920 x 1080p)
|
||||
giúp nội dung hiển thị luôn có được
|
||||
độ rõ nét. Nhờ việc sử dụng tấm nền IPS, người dùng còn có thể điều chỉnh góc
|
||||
nghiêng linh hoạt mà không gây ảnh
|
||||
hưởng tới chất lượng hình ảnh.</p>
|
||||
<p style="text-align: justify;"><img
|
||||
src="https://cdn2.cellphones.com.vn/insecure/rs:fill:0:0/q:90/plain/https://cellphones.com.vn/media/wysiwyg/laptop/HP/Victus/Laptop-hp-victus-16-r0376tx-ay8z2pa-4.jpg"
|
||||
alt="Hiển thị sắc nét và mượt mà" loading="lazy"></p>
|
||||
<p style="text-align: justify;">Điểm nổi bật có trên màn hình HP Victus 16 R0376TX
|
||||
AY8Z2PA chính là tần số quét và độ
|
||||
phủ màu. Với độ phủ màu 100% sRGB, mẫu laptop gaming HP này sẽ hỗ trợ người dùng
|
||||
làm
|
||||
các công việc liên quan tới
|
||||
sáng tạo hiệu quả. Tần số quét ở mức 165Hz sẽ giúp màn hình tái hiện các chuyển
|
||||
động
|
||||
một cách uyển chuyển, mượt mà.
|
||||
</p>
|
||||
<p style="text-align: justify;">Ngoài ra, màn hình HP Victus 16 R0376TX AY8Z2PA còn
|
||||
được
|
||||
phủ lớp chống chói và có độ
|
||||
sáng 300 nits để thoải mái sử dụng ở những nơi có ánh sáng mạnh. Với chuẩn Low
|
||||
Blue
|
||||
Light, màn hình còn giảm thiểu
|
||||
lượng ánh sáng xanh phát ra để hạn chế tình trạng mỏi mắt khi sử dụng laptop
|
||||
trong
|
||||
thời gian dài.</p>
|
||||
<h3 style="scroll-margin : 154px;"
|
||||
id="thoi-luong-pin-dai-ket-noi-phong-phu-va-on-dinh">
|
||||
<strong> Thời lượng pin dài, kết
|
||||
nối phong phú và ổn định </strong>
|
||||
</h3>
|
||||
<p style="text-align: justify;">Laptop HP Victus 16 R0376TX AY8Z2PA được trang bị
|
||||
viên
|
||||
pin Li-ion Polymer 4-cell có dung
|
||||
lượng ở mức 70Wh. Với dung lượng này, viên pin có thể duy trì trạng thái hoạt
|
||||
động
|
||||
cho laptop lên tới nhiều giờ với
|
||||
các tác vụ hỗn hợp. Laptop còn được trang bị bộ nguồn 200W Smart AC power
|
||||
adapter để
|
||||
hỗ trợ sạc pin nhanh 50% trong
|
||||
khoảng 30 phút.</p>
|
||||
<p style="text-align: justify;"><img
|
||||
src="https://cdn2.cellphones.com.vn/insecure/rs:fill:0:0/q:90/plain/https://cellphones.com.vn/media/wysiwyg/laptop/HP/Victus/Laptop-hp-victus-16-r0376tx-ay8z2pa-5.jpg"
|
||||
alt="Thời lượng pin dài, kết nối phong phú và ổn định" loading="lazy"></p>
|
||||
<p style="text-align: justify;">Để hỗ trợ việc liên kết có dây và chia sẻ dữ liệu,
|
||||
HP
|
||||
còn trang bị cho mẫu laptop Victus
|
||||
của hàng đầy đủ các cổng kết nối thông dụng. Hai cạnh bên laptop được tích hợp
|
||||
các
|
||||
cổng USB Type-A, USB Type-C,
|
||||
RJ-45, HDMI 2.1, jack audio 3.5mm và bộ chuyển đổi điện xoay chiều thông minh.
|
||||
</p>
|
||||
<p style="text-align: justify;">Laptop Victus 16 R0376TX AY8Z2PA còn được trang bị
|
||||
card
|
||||
wireless Bluetooth 5.3 và Intel
|
||||
Wi-Fi 6E AX211 (2x2). Điều này sẽ đảm bảo được khả năng kết nối với các thiết bị
|
||||
ngoại vi, kết nối mạng ổn định,
|
||||
nhanh chóng cho laptop.</p>
|
||||
<h2 style="scroll-margin : 154px;"
|
||||
id="mua-laptop-hp-victus-16-r0376tx-ay8z2pa-gia-tot-tai-cellphones"><strong> Mua
|
||||
laptop HP Victus 16 R0376TX AY8Z2PA giá tốt tại CellphoneS </strong></h2>
|
||||
`;
|
||||
|
||||
const ProductInformation = () => {
|
||||
return (
|
||||
<View style={styles.boxDesciption}>
|
||||
<Text style={styles.titleDesciption}>Thông tin sản phẩm</Text>
|
||||
<View style={styles.content}>
|
||||
<ProductHTMLContent htmlContent={productHtml} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductInformation;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
boxDesciption: {
|
||||
backgroundColor: "#fff",
|
||||
marginTop: 15,
|
||||
borderRadius: 8,
|
||||
},
|
||||
titleDesciption: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#B1B1B1",
|
||||
padding: 10,
|
||||
fontSize: 16,
|
||||
fontWeight: "bold",
|
||||
},
|
||||
content: {
|
||||
padding: 10,
|
||||
},
|
||||
heading: {
|
||||
fontSize: 18,
|
||||
fontWeight: "bold",
|
||||
marginTop: 20,
|
||||
marginBottom: 8,
|
||||
},
|
||||
subheading: {
|
||||
fontSize: 16,
|
||||
fontWeight: "600",
|
||||
marginTop: 16,
|
||||
marginBottom: 4,
|
||||
},
|
||||
paragraph: {
|
||||
fontSize: 14,
|
||||
textAlign: "justify",
|
||||
marginBottom: 12,
|
||||
},
|
||||
image: {
|
||||
width: "100%",
|
||||
height: 200,
|
||||
resizeMode: "contain",
|
||||
marginBottom: 12,
|
||||
},
|
||||
button: {
|
||||
marginTop: 10,
|
||||
alignSelf: "center",
|
||||
},
|
||||
buttonText: {
|
||||
color: "#007AFF",
|
||||
fontSize: 14,
|
||||
},
|
||||
});
|
||||
109
src/screens/product/ProductList.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
import React, { useState } from "react";
|
||||
import { useNavigation, NavigationProp } from "@react-navigation/native";
|
||||
import AppLayout from "@layouts/AppLayout";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
Image,
|
||||
FlatList,
|
||||
TouchableOpacity,
|
||||
ScrollView,
|
||||
Dimensions,
|
||||
} from "react-native";
|
||||
import { globalStyles } from "styles/globalStyles";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { Picker } from "@react-native-picker/picker";
|
||||
import ProductItem from "@components/product/ItemProduct";
|
||||
import { products } from "../../data/product";
|
||||
import FilterDropdown from "@components/product/FilterDropdown";
|
||||
import Footer from "@components/footer/Footer";
|
||||
|
||||
const ProductList = () => {
|
||||
const navigation = useNavigation<NavigationProp<any>>();
|
||||
const [selectedAddress, setSelectedAddress] = useState("");
|
||||
const [selectedBrand, setSelectedBrand] = useState("");
|
||||
|
||||
return (
|
||||
<AppLayout activeTab="productlist">
|
||||
<ScrollView>
|
||||
<View style={styles.container}>
|
||||
{/* Breadcrumb */}
|
||||
<View style={globalStyles.breadcrumb}>
|
||||
<TouchableOpacity
|
||||
style={globalStyles.breadcrumbItem}
|
||||
onPress={() => navigation.navigate("Home" as never)}
|
||||
>
|
||||
<Ionicons name="home-outline" size={20} color="#637381" />
|
||||
</TouchableOpacity>
|
||||
<Ionicons name="chevron-forward-outline" size={14} color="#999" />
|
||||
<Text style={[globalStyles.breadcrumbText, { fontWeight: "600" }]}>
|
||||
Màn hình máy tính
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<Text style={styles.nameCategory}>
|
||||
Máy tính để bàn, máy tính xách tay và linh phụ kiện
|
||||
</Text>
|
||||
|
||||
<View style={styles.boxFilter}>
|
||||
<Text>Bộ lọc</Text>
|
||||
<View style={styles.listFilter}>
|
||||
<FilterDropdown
|
||||
placeholder="Địa chỉ"
|
||||
options={["Hà Nội", "TP.HCM", "Đà Nẵng"]}
|
||||
selected={selectedAddress}
|
||||
onSelect={setSelectedAddress}
|
||||
/>
|
||||
<FilterDropdown
|
||||
placeholder="Thương hiệu"
|
||||
options={["Dell", "HP", "Lenovo"]}
|
||||
selected={selectedBrand}
|
||||
onSelect={setSelectedBrand}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.listProduct}>
|
||||
{products.map((item) => (
|
||||
<ProductItem key={item.id} product={item} />
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductList;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 10,
|
||||
marginBottom: 60,
|
||||
},
|
||||
nameCategory: {
|
||||
fontSize: 16,
|
||||
fontWeight: 700,
|
||||
},
|
||||
listFilter: {
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
marginRight: -5,
|
||||
},
|
||||
boxFilter: {
|
||||
marginTop: 10,
|
||||
paddingLeft: 10,
|
||||
paddingTop: 10,
|
||||
backgroundColor: "#f5f5f5",
|
||||
},
|
||||
listProduct: {
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
paddingTop: 10,
|
||||
gap: 10,
|
||||
paddingBottom: 10,
|
||||
},
|
||||
});
|
||||
111
src/screens/product/ProductListBig.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
import React from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
Image,
|
||||
FlatList,
|
||||
TouchableOpacity,
|
||||
ScrollView,
|
||||
Dimensions,
|
||||
} from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { useNavigation, NavigationProp } from "@react-navigation/native";
|
||||
import AppLayout from "@layouts/AppLayout";
|
||||
import { globalStyles } from "styles/globalStyles";
|
||||
import Footer from "@components/footer/Footer";
|
||||
|
||||
const screenWidth = Dimensions.get("window").width;
|
||||
const numColumns = 2;
|
||||
|
||||
const categories = Array.from({ length: 12 }, (_, index) => ({
|
||||
id: index + 1,
|
||||
title: "Máy chủ",
|
||||
image: require("../../../assets/images/category-avatar.png"),
|
||||
link: "productlistmain",
|
||||
}));
|
||||
|
||||
const ProductListBig = () => {
|
||||
const navigation = useNavigation<NavigationProp<any>>();
|
||||
|
||||
const renderItem = ({ item }: { item: (typeof categories)[0] }) => (
|
||||
<TouchableOpacity
|
||||
style={styles.card}
|
||||
onPress={() => navigation.navigate(item.link as never)}
|
||||
>
|
||||
<Image source={item.image} style={styles.image} resizeMode="contain" />
|
||||
<Text style={styles.title} numberOfLines={1}>
|
||||
{item.title}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
return (
|
||||
<AppLayout activeTab="productlist">
|
||||
<ScrollView>
|
||||
<View style={styles.container}>
|
||||
{/* Breadcrumb */}
|
||||
<View style={globalStyles.breadcrumb}>
|
||||
<TouchableOpacity
|
||||
style={globalStyles.breadcrumbItem}
|
||||
onPress={() => navigation.navigate("Home" as never)}
|
||||
>
|
||||
<Ionicons name="home-outline" size={20} color="#637381" />
|
||||
</TouchableOpacity>
|
||||
<Ionicons name="chevron-forward-outline" size={14} color="#999" />
|
||||
<Text style={[globalStyles.breadcrumbText, { fontWeight: "600" }]}>
|
||||
Màn hình máy tính
|
||||
</Text>
|
||||
</View>
|
||||
<FlatList
|
||||
data={categories}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={(item) => item.id.toString()}
|
||||
numColumns={numColumns}
|
||||
contentContainerStyle={styles.grid}
|
||||
columnWrapperStyle={styles.columnWrapper}
|
||||
showsVerticalScrollIndicator={false}
|
||||
/>
|
||||
</View>
|
||||
<Footer navigation={navigation} />
|
||||
</ScrollView>
|
||||
</AppLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductListBig;
|
||||
|
||||
const itemWidth = screenWidth / numColumns - 17;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 10,
|
||||
},
|
||||
grid: {
|
||||
paddingVertical: 10,
|
||||
},
|
||||
columnWrapper: {
|
||||
justifyContent: "space-between",
|
||||
marginBottom: 10,
|
||||
},
|
||||
card: {
|
||||
width: itemWidth,
|
||||
borderWidth: 1,
|
||||
borderColor: "#c0c0c0",
|
||||
borderRadius: 8,
|
||||
padding: 10,
|
||||
alignItems: "center",
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
image: {
|
||||
width: itemWidth,
|
||||
height: 100,
|
||||
marginBottom: 10,
|
||||
},
|
||||
title: {
|
||||
textAlign: "center",
|
||||
fontSize: 16,
|
||||
fontWeight: "600",
|
||||
},
|
||||
});
|
||||
110
src/screens/product/ProductSpecification.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
FlatList,
|
||||
StyleSheet,
|
||||
} from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
|
||||
const MAX_VISIBLE_ROWS = 6;
|
||||
|
||||
const specificationData = [
|
||||
{ label: "Mã sản phẩm", value: "VA3416WC" },
|
||||
{ label: "Màu sắc", value: "Đen" },
|
||||
{ label: "Độ sáng", value: "Max 300cd/m²" },
|
||||
{ label: "Độ tương phản", value: "3000:1" },
|
||||
{ label: "Màu sắc hiển thị", value: "16.7M" },
|
||||
{ label: "Màu sắc hỗ trợ", value: "6500K" },
|
||||
{ label: "Loại màn hình", value: "Cong R1500" },
|
||||
{ label: "Kích cỡ màn hình", value: '34"' },
|
||||
{ label: "Tấm nền", value: "VA" },
|
||||
{ label: "Góc nhìn", value: "89°/89° (H/V)" },
|
||||
{
|
||||
label: "Tính năng đặc biệt",
|
||||
value: `1. Flicker-Free Backlight adjustment\n2. Dynamic Contrast Ratio: DCR\n3. Adaptive Sync\n4. FPS/RTS\n5. PIP/PBP\n6. PQ\n7. GAME PLUS`,
|
||||
},
|
||||
];
|
||||
|
||||
const ProductSpecification = () => {
|
||||
const [showAll, setShowAll] = useState(false);
|
||||
|
||||
const visibleData = showAll
|
||||
? specificationData
|
||||
: specificationData.slice(0, MAX_VISIBLE_ROWS);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>Thông tin chi tiết</Text>
|
||||
<FlatList
|
||||
data={visibleData}
|
||||
keyExtractor={(item, index) => `${item.label}-${index}`}
|
||||
renderItem={({ item }) => (
|
||||
<View style={styles.row}>
|
||||
<Text style={styles.label}>{item.label}</Text>
|
||||
<Text style={styles.value}>{item.value}</Text>
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
|
||||
{specificationData.length > MAX_VISIBLE_ROWS && (
|
||||
<TouchableOpacity
|
||||
onPress={() => setShowAll(!showAll)}
|
||||
style={styles.toggleButton}
|
||||
>
|
||||
<Text style={styles.toggleText}>
|
||||
{showAll ? "Thu gọn" : "Xem thêm thông số"}{" "}
|
||||
<Ionicons
|
||||
name={showAll ? "chevron-up-outline" : "chevron-down-outline"}
|
||||
size={16}
|
||||
color="#FF7A00"
|
||||
/>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductSpecification;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: "#fff",
|
||||
borderRadius: 8,
|
||||
padding: 12,
|
||||
marginTop: 15,
|
||||
},
|
||||
title: {
|
||||
fontSize: 18,
|
||||
fontWeight: "bold",
|
||||
marginBottom: 12,
|
||||
borderBottomWidth: 1,
|
||||
borderColor: "#B1B1B1",
|
||||
paddingBottom: 8,
|
||||
},
|
||||
row: {
|
||||
flexDirection: "row",
|
||||
marginBottom: 8,
|
||||
},
|
||||
label: {
|
||||
flex: 1,
|
||||
fontWeight: "600",
|
||||
color: "#333",
|
||||
},
|
||||
value: {
|
||||
flex: 1,
|
||||
color: "#555",
|
||||
},
|
||||
toggleButton: {
|
||||
marginTop: 12,
|
||||
alignItems: "center",
|
||||
},
|
||||
toggleText: {
|
||||
color: "#FF7A00",
|
||||
fontWeight: "600",
|
||||
fontSize: 14,
|
||||
flexDirection: "row",
|
||||
},
|
||||
});
|
||||
133
src/screens/product/SupplierList.tsx
Normal file
@@ -0,0 +1,133 @@
|
||||
import React from "react";
|
||||
import {
|
||||
View,
|
||||
ScrollView,
|
||||
Text,
|
||||
StyleSheet,
|
||||
TextInput,
|
||||
Dimensions,
|
||||
} from "react-native";
|
||||
import SupplierItem from "@components/product/SupplierItem";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import Feather from "@expo/vector-icons/Feather";
|
||||
const { width } = Dimensions.get("window");
|
||||
|
||||
const SupplierList = () => {
|
||||
const suppliers = [
|
||||
{
|
||||
name: "Hanoicomputer",
|
||||
distance: "3km",
|
||||
rating: 4.7,
|
||||
logo: require("../../../assets/images/logo-hacom.png"),
|
||||
shippingPolicy:
|
||||
"Miễn phí giao hàng\nNhận giao hàng và lắp đặt từ 8h00-21h30 các ngày trong tuần kể cả Thứ 7, CN",
|
||||
priceRange: "9.000.000đ - 20.000.000đ",
|
||||
hasVAT: true,
|
||||
products: ["8GB - 9.000.000đ new White", "8GB - 9.000.000đ new White"],
|
||||
},
|
||||
{
|
||||
name: "Hanoicomputer",
|
||||
distance: "3km",
|
||||
rating: 4.7,
|
||||
logo: require("../../../assets/images/logo-hacom.png"),
|
||||
shippingPolicy:
|
||||
"Miễn phí giao hàng\nNhận giao hàng và lắp đặt từ 8h00-21h30 các ngày trong tuần kể cả Thứ 7, CN",
|
||||
priceRange: "9.000.000đ - 20.000.000đ",
|
||||
hasVAT: true,
|
||||
products: ["8GB - 9.000.000đ new White", "8GB - 9.000.000đ new White"],
|
||||
},
|
||||
{
|
||||
name: "Hanoicomputer",
|
||||
distance: "3km",
|
||||
rating: 4.7,
|
||||
logo: require("../../../assets/images/logo-hacom.png"),
|
||||
shippingPolicy:
|
||||
"Miễn phí giao hàng\nNhận giao hàng và lắp đặt từ 8h00-21h30 các ngày trong tuần kể cả Thứ 7, CN",
|
||||
priceRange: "9.000.000đ - 20.000.000đ",
|
||||
hasVAT: true,
|
||||
products: ["8GB - 9.000.000đ new White", "8GB - 9.000.000đ new White"],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
style={{
|
||||
padding: 10,
|
||||
backgroundColor: "#fff",
|
||||
marginTop: 15,
|
||||
borderRadius: 4,
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
paddingBottom: 15,
|
||||
}}
|
||||
>
|
||||
<Text style={{ fontSize: 16, fontWeight: "bold" }}>
|
||||
Nhà cung cấp trên BestPC - Tại Hà Nội
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.Form}>
|
||||
<Feather name="map-pin" size={20} color="#a6a6a6" />{" "}
|
||||
<TextInput
|
||||
placeholder="Nhập địa chỉ của bạn để tìm NCC gần nhất"
|
||||
style={styles.inputMap}
|
||||
placeholderTextColor="#666"
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* List */}
|
||||
{suppliers.map((item, index) => (
|
||||
<SupplierItem key={index} {...item} />
|
||||
))}
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
marginTop: 10,
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
textAlign: "center",
|
||||
color: "#FF7A00",
|
||||
fontSize: 16,
|
||||
}}
|
||||
>
|
||||
Xem thêm
|
||||
</Text>
|
||||
<Ionicons
|
||||
name="chevron-down"
|
||||
style={{ marginLeft: 5 }}
|
||||
size={16}
|
||||
color="#FF7A00"
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupplierList;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
Form: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
position: "relative",
|
||||
borderWidth: 1,
|
||||
borderColor: "#b1b1b1",
|
||||
marginRight: 10,
|
||||
width: width - 40,
|
||||
height: 45,
|
||||
paddingHorizontal: 10,
|
||||
borderRadius: 4,
|
||||
},
|
||||
inputMap: {
|
||||
width: "100%",
|
||||
},
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
// src/styles/globalStyles.ts
|
||||
import { StyleSheet, Dimensions } from 'react-native';
|
||||
var winWidth = Dimensions.get("window").width;
|
||||
const itemWidth = (winWidth - 40) / 4;
|
||||
|
||||
export const globalStyles = StyleSheet.create({
|
||||
boxProductReviewTop: {
|
||||
@@ -50,7 +51,7 @@ export const globalStyles = StyleSheet.create({
|
||||
marginBottom: 10,
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
marginLeft: -10,
|
||||
gap: 10
|
||||
},
|
||||
moreAll: {
|
||||
width: 110,
|
||||
@@ -80,9 +81,12 @@ export const globalStyles = StyleSheet.create({
|
||||
},
|
||||
listCategoryBox: {
|
||||
marginTop: 10,
|
||||
padding: 10,
|
||||
height: 300
|
||||
},
|
||||
categoryItem: {
|
||||
width: '100%',
|
||||
width: '25%',
|
||||
marginBottom: 25
|
||||
},
|
||||
boxImageCategory: {
|
||||
width: 70,
|
||||
@@ -103,6 +107,283 @@ export const globalStyles = StyleSheet.create({
|
||||
fontWeight: '500',
|
||||
marginTop: 5,
|
||||
textAlign: 'center',
|
||||
}
|
||||
|
||||
},
|
||||
dot: {
|
||||
backgroundColor: 'rgba(0,0,0,.2)',
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 4,
|
||||
margin: 3,
|
||||
},
|
||||
activeDot: {
|
||||
backgroundColor: '#ff7a00',
|
||||
width: 40,
|
||||
height: 10,
|
||||
borderRadius: 5,
|
||||
margin: 3,
|
||||
},
|
||||
BoxBusiness: {
|
||||
marginTop: 25,
|
||||
},
|
||||
textBoxBusiness: {
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
color: "#0d0d9c",
|
||||
marginBottom: 8,
|
||||
textTransform: "uppercase",
|
||||
textAlign: "center",
|
||||
},
|
||||
sliderBusinesses: {
|
||||
marginTop: 20,
|
||||
height: 85
|
||||
},
|
||||
logoItem: {
|
||||
width: itemWidth,
|
||||
height: 40,
|
||||
borderRadius: 8,
|
||||
backgroundColor: '#fff',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: 10,
|
||||
shadowColor: '#727272',
|
||||
shadowOffset: { width: 1, height: 2 },
|
||||
shadowOpacity: 0.25,
|
||||
shadowRadius: 4,
|
||||
},
|
||||
logoImage: {
|
||||
width: 80,
|
||||
height: 30,
|
||||
resizeMode: 'contain',
|
||||
},
|
||||
BoxProductSaveHome: {
|
||||
marginTop: 20,
|
||||
width: winWidth,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
},
|
||||
textBoxProductSaveHome: {
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
color: "#0d0d9c",
|
||||
marginBottom: 8,
|
||||
textTransform: "uppercase",
|
||||
textAlign: "center",
|
||||
},
|
||||
BoxArticleBranch: {
|
||||
width: winWidth,
|
||||
marginTop: 25
|
||||
},
|
||||
textBoxArticleBranche: {
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
color: "#111189ff",
|
||||
marginBottom: 8,
|
||||
textTransform: "uppercase",
|
||||
textAlign: "center",
|
||||
},
|
||||
boxFlex: {
|
||||
alignItems: "center",
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
margin: 'auto',
|
||||
},
|
||||
boxListArticle: {
|
||||
marginTop: 5,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
},
|
||||
flex: {
|
||||
alignItems: "center",
|
||||
flexDirection: 'row',
|
||||
},
|
||||
itemArtTime: {
|
||||
alignItems: "center",
|
||||
flexDirection: 'row',
|
||||
},
|
||||
itemArticle: {
|
||||
flexDirection: 'row',
|
||||
marginBottom: 15,
|
||||
paddingBottom: 15,
|
||||
borderBottomWidth: 1,
|
||||
borderColor: '#efefef'
|
||||
},
|
||||
itemArticleImg: {
|
||||
width: 90,
|
||||
height: 90,
|
||||
marginRight: 10,
|
||||
},
|
||||
imgArticle: {
|
||||
width: '100%',
|
||||
height: "100%",
|
||||
objectFit: 'cover',
|
||||
},
|
||||
infoArticle: {
|
||||
width: winWidth - 120
|
||||
},
|
||||
itemArtName: {
|
||||
fontSize: 15,
|
||||
fontWeight: 700,
|
||||
marginBottom: 3,
|
||||
},
|
||||
itemArtSummary: {
|
||||
fontSize: 13,
|
||||
color: '#161616',
|
||||
},
|
||||
itemArtDate: {
|
||||
fontSize: 13,
|
||||
marginLeft: 3
|
||||
},
|
||||
itemArtSource: {
|
||||
fontSize: 12,
|
||||
marginLeft: 3
|
||||
},
|
||||
btnMore: {
|
||||
margin: 'auto',
|
||||
width: 90,
|
||||
height: 28,
|
||||
lineHeight: 28,
|
||||
textAlign: 'center',
|
||||
borderWidth: 1,
|
||||
borderColor: '#ff7a00',
|
||||
borderRadius: 4,
|
||||
color: '#ff7a00',
|
||||
fontSize: 13,
|
||||
fontWeight: 700
|
||||
},
|
||||
itemArtlocal: {
|
||||
flexDirection: 'row',
|
||||
alignItems: "center"
|
||||
},
|
||||
textArtlocal: {
|
||||
marginLeft: 3,
|
||||
fontSize: 13,
|
||||
paddingBottom: 2
|
||||
},
|
||||
itemArtUploadtime: {
|
||||
flexDirection: 'row',
|
||||
alignItems: "center",
|
||||
marginBottom: 3
|
||||
},
|
||||
itemArtUser: {
|
||||
flexDirection: 'row',
|
||||
alignItems: "center",
|
||||
},
|
||||
imgAvatar: {
|
||||
width: 20,
|
||||
height: 20,
|
||||
objectFit: 'contain',
|
||||
marginRight: 3
|
||||
},
|
||||
itemArtNameUser: {
|
||||
fontWeight: "bold",
|
||||
},
|
||||
itemArtPrice: {
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
color: '#d80a00',
|
||||
},
|
||||
BoxBannerSaleHome: {
|
||||
margin: 10,
|
||||
marginTop: 30,
|
||||
},
|
||||
imgBannerSale: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover',
|
||||
borderRadius: 12
|
||||
},
|
||||
sliderBannerSale: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
height: 200
|
||||
},
|
||||
itemBannerSale: {
|
||||
width: winWidth - 50,
|
||||
height: 160,
|
||||
objectFit: 'cover',
|
||||
marginRight: 10
|
||||
},
|
||||
BoxPromotionHome: {
|
||||
marginTop: 20
|
||||
},
|
||||
touchArea: {
|
||||
width: winWidth,
|
||||
height: 200,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
borderRadius: 12
|
||||
},
|
||||
imageYoutobe: {
|
||||
width: winWidth - 20,
|
||||
height: 200,
|
||||
objectFit: 'cover',
|
||||
overflow: 'hidden',
|
||||
borderRadius: 12
|
||||
},
|
||||
boxVideo: {
|
||||
width: winWidth - 20,
|
||||
height: 200,
|
||||
},
|
||||
containerVideo: {
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10
|
||||
},
|
||||
iconPlay: {
|
||||
position: 'absolute',
|
||||
left: winWidth / 2 - 20,
|
||||
top: 90,
|
||||
zIndex: 10,
|
||||
},
|
||||
infoVideo: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
padding: 12,
|
||||
zIndex: 10,
|
||||
borderBottomLeftRadius: 16,
|
||||
borderBottomRightRadius: 16,
|
||||
},
|
||||
listEvenBanner: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
marginTop: 10,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
marginRight: -10
|
||||
},
|
||||
itemEven: {
|
||||
width: winWidth / 2 - 20,
|
||||
height: 100,
|
||||
marginRight: 10,
|
||||
marginBottom: 10
|
||||
},
|
||||
overlay: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
height: '100%',
|
||||
width: winWidth - 20,
|
||||
backgroundColor: 'rgba(0,0,0,0.4)',
|
||||
zIndex: 1,
|
||||
borderRadius: 20
|
||||
},
|
||||
imgEven: {
|
||||
width: '100%',
|
||||
height: 100,
|
||||
objectFit: 'cover',
|
||||
borderRadius: 8
|
||||
},
|
||||
breadcrumb: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
paddingVertical: 10,
|
||||
},
|
||||
breadcrumbItem: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginRight: 6,
|
||||
},
|
||||
breadcrumbText: {
|
||||
marginLeft: 4,
|
||||
color: "#637381",
|
||||
fontSize: 14,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,7 +4,16 @@
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"baseUrl": "src",
|
||||
"paths": {
|
||||
"@components/*": ["components/*"],
|
||||
"@layouts/*": ["layouts/*"],
|
||||
"@screens/*": ["screens/*"],
|
||||
"@assets/*": ["assets/*"],
|
||||
"@navigation/*": ["navigation/*"]
|
||||
}
|
||||
},
|
||||
|
||||
"include": ["src/**/*", "assets/**/*"]
|
||||
}
|
||||
|
||||