update
6
.env
@@ -1,3 +1,3 @@
|
|||||||
EXPO_HOME=D:/bestpc_mobile/.expo
|
EXPO_HOME=C:/Users/tiepb/Downloads/Company/work_2025/bestpc_mobile/.expo
|
||||||
EXPO_CACHE_DIR=D:/bestpc_mobile/.expo/cache
|
EXPO_CACHE_DIR=C:/Users/tiepb/Downloads/Company/work_2025/bestpc_mobile/.expo/cache
|
||||||
EXPO_PROJECT_DIR=D:/bestpc_mobile
|
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 React from "react";
|
||||||
import { StyleSheet, ScrollView } from "react-native";
|
|
||||||
import { SafeAreaProvider } from "react-native-safe-area-context";
|
|
||||||
import { NavigationContainer } from "@react-navigation/native";
|
import { NavigationContainer } from "@react-navigation/native";
|
||||||
import {
|
import { SafeAreaProvider } from "react-native-safe-area-context";
|
||||||
createStackNavigator,
|
import AppNavigator from "./src/navigation/AppNavigator";
|
||||||
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";
|
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<SafeAreaProvider>
|
<SafeAreaProvider>
|
||||||
<Header />
|
|
||||||
<NavigationContainer>
|
<NavigationContainer>
|
||||||
<AllPage />
|
<AppNavigator />
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
{/* <Footer /> */}
|
|
||||||
</SafeAreaProvider>
|
</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,
|
// It also ensures that whether you load the app in Expo Go or in a native build,
|
||||||
// the environment is set up appropriately
|
// the environment is set up appropriately
|
||||||
registerRootComponent(App);
|
registerRootComponent(App);
|
||||||
|
|
||||||
|
|||||||
39049
package-lock.json
generated
14
package.json
@@ -14,30 +14,40 @@
|
|||||||
"@expo/vector-icons": "^14.1.0",
|
"@expo/vector-icons": "^14.1.0",
|
||||||
"@react-native-picker/picker": "^2.11.0",
|
"@react-native-picker/picker": "^2.11.0",
|
||||||
"@react-navigation/drawer": "^7.3.12",
|
"@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/native-stack": "^7.3.13",
|
||||||
"@react-navigation/stack": "^7.3.2",
|
"@react-navigation/stack": "^7.3.2",
|
||||||
"dotenv": "^16.5.0",
|
"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",
|
"expo-status-bar": "~2.2.3",
|
||||||
"hermes-engine": "^0.11.0",
|
"hermes-engine": "^0.11.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"metro-runtime": "^0.82.3",
|
"metro-runtime": "^0.82.3",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-native": "^0.79.2",
|
"react-native": "^0.79.2",
|
||||||
|
"react-native-collapsible": "^1.6.2",
|
||||||
"react-native-gesture-handler": "~2.24.0",
|
"react-native-gesture-handler": "~2.24.0",
|
||||||
"react-native-reanimated": "~3.17.4",
|
"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-safe-area-context": "^5.4.0",
|
||||||
"react-native-screens": "~4.10.0",
|
"react-native-screens": "~4.10.0",
|
||||||
"react-native-swiper": "^1.6.0",
|
"react-native-swiper": "^1.6.0",
|
||||||
"react-native-web": "^0.20.0",
|
"react-native-web": "^0.20.0",
|
||||||
|
"react-native-webview": "13.13.5",
|
||||||
"react-navigation": "^5.0.0"
|
"react-navigation": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@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": "~19.0.10",
|
||||||
"@types/react-native": "^0.73.0",
|
"@types/react-native": "^0.73.0",
|
||||||
|
"babel-plugin-module-resolver": "^5.0.2",
|
||||||
"expo": "^53.0.9",
|
"expo": "^53.0.9",
|
||||||
|
"metro-react-native-babel-preset": "^0.77.0",
|
||||||
"typescript": "~5.8.3"
|
"typescript": "~5.8.3"
|
||||||
},
|
},
|
||||||
"private": true
|
"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 React, { useState } from "react";
|
||||||
import { View, Text, StyleSheet, Image, TouchableOpacity } from "react-native";
|
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 = {
|
var winWidth = Dimensions.get("window").width; //full width
|
||||||
label: string;
|
|
||||||
icon: string;
|
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) => (
|
const Footer: React.FC<Props> = ({ navigation, activeTab = "homepage" }) => {
|
||||||
<TouchableOpacity style={styles.footerItem}>
|
const [activeIndex, setActiveIndex] = useState(null);
|
||||||
<Text style={styles.footerItemText}>{label}</Text>
|
|
||||||
<Image
|
const toggleAccordion = (index: any) => {
|
||||||
source={{ uri: icon }}
|
setActiveIndex(index === activeIndex ? null : index);
|
||||||
style={styles.footerItemIcon}
|
};
|
||||||
resizeMode="contain"
|
|
||||||
|
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>
|
</TouchableOpacity>
|
||||||
);
|
<Collapsible collapsed={activeIndex !== index}>
|
||||||
|
{item.links?.map((link, linkIndex) => (
|
||||||
const Footer = () => {
|
<TouchableOpacity
|
||||||
return (
|
key={linkIndex}
|
||||||
<View style={styles.container}>
|
style={styles.linkItem}
|
||||||
<View style={styles.spacer} />
|
onPress={() => handleLinkPress(link.route)}
|
||||||
<View style={styles.content}>
|
>
|
||||||
<FooterItem
|
<Text style={styles.linkText}>{link.title}</Text>
|
||||||
label="Về chúng tôi"
|
</TouchableOpacity>
|
||||||
icon="https://cdn.builder.io/api/v1/image/assets/TEMP/0f5cda0be55412240422e2274330e3f6e64023d3?placeholderIfAbsent=true&apiKey=1fa9f06a1e81406d92148011750a3756"
|
))}
|
||||||
/>
|
</Collapsible>
|
||||||
<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"
|
|
||||||
/>
|
|
||||||
</View>
|
</View>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
footer: {
|
||||||
alignSelf: "stretch",
|
|
||||||
marginTop: 28,
|
|
||||||
width: "100%",
|
width: "100%",
|
||||||
paddingBottom: 21,
|
marginTop: 20,
|
||||||
},
|
},
|
||||||
spacer: {
|
spacer: {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
minHeight: 10,
|
minHeight: 10,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
|
backgroundColor: "#1c039b",
|
||||||
},
|
},
|
||||||
content: {
|
accordionContainer: {
|
||||||
marginTop: 17,
|
|
||||||
width: "100%",
|
|
||||||
paddingLeft: 10,
|
paddingLeft: 10,
|
||||||
paddingRight: 10,
|
paddingTop: 16,
|
||||||
|
marginBottom: 60,
|
||||||
|
width: winWidth - 10,
|
||||||
},
|
},
|
||||||
footerItem: {
|
accordionHeader: {
|
||||||
borderRadius: 4,
|
backgroundColor: "#f5f5f5",
|
||||||
display: "flex",
|
padding: 14,
|
||||||
paddingLeft: 9,
|
borderRadius: 8,
|
||||||
paddingRight: 9,
|
|
||||||
paddingTop: 6,
|
|
||||||
paddingBottom: 13,
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
},
|
},
|
||||||
footerItemText: {
|
accordionTitle: {
|
||||||
color: "#444",
|
fontSize: 16,
|
||||||
fontFamily: "Shopee Display, -apple-system, Roboto, Helvetica, sans-serif",
|
color: "#333",
|
||||||
fontSize: 13,
|
fontWeight: 700,
|
||||||
fontWeight: "700",
|
|
||||||
},
|
},
|
||||||
footerItemIcon: {
|
accordionContent: {
|
||||||
width: 11,
|
backgroundColor: "#fff",
|
||||||
height: 6,
|
padding: 12,
|
||||||
marginTop: 7,
|
marginBottom: 10,
|
||||||
|
color: "#555",
|
||||||
},
|
},
|
||||||
logo: {
|
linkItem: {
|
||||||
width: 95,
|
paddingVertical: 8,
|
||||||
height: 40,
|
paddingLeft: 20,
|
||||||
marginTop: 17,
|
},
|
||||||
marginLeft: 10,
|
linkText: {
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 500,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -223,20 +223,22 @@ const styles = StyleSheet.create({
|
|||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
paddingLeft: 10,
|
paddingLeft: 10,
|
||||||
paddingRight: 10,
|
paddingRight: 10,
|
||||||
paddingTop: 6,
|
height: 32,
|
||||||
paddingBottom: 6,
|
lineHeight: 32,
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
backgroundColor: "#FFFFFF",
|
backgroundColor: "#FFFFFF",
|
||||||
},
|
},
|
||||||
searchInput: {
|
searchInput: {
|
||||||
flex: 1,
|
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontFamily: "Roboto, -apple-system, Roboto, Helvetica, sans-serif",
|
|
||||||
fontWeight: "500",
|
fontWeight: "500",
|
||||||
color: "#000000",
|
color: "#000000",
|
||||||
height: 32,
|
height: 32,
|
||||||
|
lineHeight: 32,
|
||||||
|
paddingTop: 7,
|
||||||
|
marginTop: 5,
|
||||||
|
width: winWidth - 60,
|
||||||
},
|
},
|
||||||
searchIconContainer: {
|
searchIconContainer: {
|
||||||
flexDirection: "row",
|
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,
|
Dimensions,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
|
|
||||||
|
import { useNavigation } from "@react-navigation/native";
|
||||||
|
|
||||||
var winWidth = Dimensions.get("window").width; //full width
|
var winWidth = Dimensions.get("window").width; //full width
|
||||||
var winHeight = Dimensions.get("window").height;
|
var winHeight = Dimensions.get("window").height;
|
||||||
|
|
||||||
const ItemProduct = ({ product }: { product: any }) => {
|
const ItemProduct = ({ product }: { product: any }) => {
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
function formatCurrency(a: number | string): string {
|
function formatCurrency(a: number | string): string {
|
||||||
let b = parseFloat(a.toString())
|
let b = parseFloat(a.toString())
|
||||||
.toFixed(2)
|
.toFixed(2)
|
||||||
@@ -25,7 +29,10 @@ const ItemProduct = ({ product }: { product: any }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.productItem}>
|
<View style={styles.productItem}>
|
||||||
<TouchableOpacity style={styles.productImage}>
|
<TouchableOpacity
|
||||||
|
onPress={() => navigation.navigate("productdetail" as never)}
|
||||||
|
style={styles.productImage}
|
||||||
|
>
|
||||||
<Image
|
<Image
|
||||||
source={{ uri: product.productImage.large }}
|
source={{ uri: product.productImage.large }}
|
||||||
style={styles.productImg}
|
style={styles.productImg}
|
||||||
@@ -37,7 +44,9 @@ const ItemProduct = ({ product }: { product: any }) => {
|
|||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<View>
|
<View>
|
||||||
<TouchableOpacity>
|
<TouchableOpacity
|
||||||
|
onPress={() => navigation.navigate("productdetail" as never)}
|
||||||
|
>
|
||||||
<Text numberOfLines={2} style={styles.productName}>
|
<Text numberOfLines={2} style={styles.productName}>
|
||||||
{product.productName}
|
{product.productName}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -53,7 +62,7 @@ const ItemProduct = ({ product }: { product: any }) => {
|
|||||||
<Image
|
<Image
|
||||||
source={
|
source={
|
||||||
product.review.rate !== undefined
|
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")
|
: require("../../../assets/images/icon_star_0.png")
|
||||||
}
|
}
|
||||||
style={styles.iconReviewRating}
|
style={styles.iconReviewRating}
|
||||||
@@ -83,19 +92,18 @@ const ItemProduct = ({ product }: { product: any }) => {
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
productItem: {
|
productItem: {
|
||||||
width: winWidth / 2 - 20,
|
width: winWidth / 2 - 20,
|
||||||
marginRight: 10,
|
padding: 10,
|
||||||
marginBottom: 10,
|
borderWidth: 1,
|
||||||
padding: 12,
|
borderColor: "#d3d3d3",
|
||||||
|
borderRadius: 8,
|
||||||
|
backgroundColor: "#fff",
|
||||||
},
|
},
|
||||||
productImage: {
|
productImage: {
|
||||||
width: winWidth / 2 - 20,
|
width: winWidth / 2 - 44,
|
||||||
height: 150,
|
height: 150,
|
||||||
position: "relative",
|
position: "relative",
|
||||||
marginBottom: 5,
|
marginBottom: 5,
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: "#d3d3d3",
|
|
||||||
backgroundColor: "#fff",
|
backgroundColor: "#fff",
|
||||||
borderRadius: 8,
|
|
||||||
},
|
},
|
||||||
productImg: {
|
productImg: {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
@@ -189,7 +197,7 @@ const styles = StyleSheet.create({
|
|||||||
height: 18,
|
height: 18,
|
||||||
},
|
},
|
||||||
storeName: {
|
storeName: {
|
||||||
fontSize: 13,
|
fontSize: 12,
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
color: "#000",
|
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",
|
name: "Pc văn phòng",
|
||||||
image: "../../assets/images/category-pc.png",
|
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 { createStackNavigator } from "@react-navigation/stack";
|
||||||
import { NavigationContainer } from "@react-navigation/native";
|
import { NavigationContainer } from "@react-navigation/native";
|
||||||
import HomeScreen from "../screens/HomeScreen";
|
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 Stack = createStackNavigator();
|
||||||
|
|
||||||
const AppNavigator: React.FC = () => {
|
const AppNavigator: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<NavigationContainer>
|
<Stack.Navigator
|
||||||
<Stack.Navigator initialRouteName="Home">
|
initialRouteName="homepage"
|
||||||
<Stack.Screen name="Home" component={HomeScreen} />
|
screenOptions={{ headerShown: false }}
|
||||||
<Stack.Screen name="Product" />
|
>
|
||||||
|
<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>
|
</Stack.Navigator>
|
||||||
</NavigationContainer>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// src/screens/HomeScreen.tsx
|
// src/screens/HomeScreen.tsx
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
import { useNavigation, NavigationProp } from "@react-navigation/native";
|
||||||
import {
|
import {
|
||||||
View,
|
View,
|
||||||
Text,
|
Text,
|
||||||
@@ -16,21 +17,37 @@ import Swiper from "react-native-swiper";
|
|||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { products } from "../data/product";
|
import { products } from "../data/product";
|
||||||
import ProductItem from "../components/product/ItemProduct";
|
import ProductItem from "../components/product/ItemProduct";
|
||||||
|
import ProductItemSave from "../components/product/itemProductSave";
|
||||||
import { categories } from "../data/category";
|
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 winWidth = Dimensions.get("window").width; //full width
|
||||||
var winHeight = Dimensions.get("window").height; //full height
|
var winHeight = Dimensions.get("window").height; //full height
|
||||||
const ratio = winWidth / 930;
|
const ratio = winWidth / 930;
|
||||||
const HomeScreen: React.FC = () => {
|
const HomeScreen: React.FC = () => {
|
||||||
|
const navigation = useNavigation<NavigationProp<any>>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container}>
|
<AppLayout activeTab="homepage">
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<SliderHome />
|
<SliderHome />
|
||||||
<BoxMenuHome />
|
<BoxMenuHome />
|
||||||
<BoxProductReviewTop />
|
<BoxProductReviewTop />
|
||||||
<BoxCategoryHome />
|
<BoxCategoryHome />
|
||||||
|
<BoxBusiness />
|
||||||
|
<BoxProductSaveHome />
|
||||||
|
<BoxArticleBranch />
|
||||||
|
<BoxArticleSale />
|
||||||
|
<BoxArticleClassifieds />
|
||||||
|
<BoxBannerSaleHome />
|
||||||
|
<BoxPromotionHome />
|
||||||
|
<Footer navigation={navigation} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</SafeAreaView>
|
</AppLayout>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,28 +81,28 @@ const SliderHome = () => {
|
|||||||
<Image
|
<Image
|
||||||
style={styles.imgSlider}
|
style={styles.imgSlider}
|
||||||
source={require("../../assets/images/banner_slider.png")}
|
source={require("../../assets/images/banner_slider.png")}
|
||||||
resizeMode="contain"
|
resizeMode="cover"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.imgContainer}>
|
<View style={styles.imgContainer}>
|
||||||
<Image
|
<Image
|
||||||
style={styles.imgSlider}
|
style={styles.imgSlider}
|
||||||
source={require("../../assets/images/banner_slider.png")}
|
source={require("../../assets/images/banner_slider.png")}
|
||||||
resizeMode="contain"
|
resizeMode="cover"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.imgContainer}>
|
<View style={styles.imgContainer}>
|
||||||
<Image
|
<Image
|
||||||
style={styles.imgSlider}
|
style={styles.imgSlider}
|
||||||
source={require("../../assets/images/banner_slider.png")}
|
source={require("../../assets/images/banner_slider.png")}
|
||||||
resizeMode="contain"
|
resizeMode="cover"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.imgContainer}>
|
<View style={styles.imgContainer}>
|
||||||
<Image
|
<Image
|
||||||
style={styles.imgSlider}
|
style={styles.imgSlider}
|
||||||
source={require("../../assets/images/banner_slider.png")}
|
source={require("../../assets/images/banner_slider.png")}
|
||||||
resizeMode="contain"
|
resizeMode="cover"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</Swiper>
|
</Swiper>
|
||||||
@@ -230,11 +247,30 @@ const BoxProductReviewTop = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const BoxCategoryHome = () => {
|
const BoxCategoryHome = () => {
|
||||||
|
const chunkedItems = chunk(categories, 8);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={globalStyles.boxCategoryHome}>
|
<View style={globalStyles.boxCategoryHome}>
|
||||||
<Text style={globalStyles.textBoxCategoryHome}>Tìm theo danh mục</Text>
|
<Text style={globalStyles.textBoxCategoryHome}>Tìm theo danh mục</Text>
|
||||||
<View style={globalStyles.listCategoryBox}>
|
<Swiper
|
||||||
{categories.map((item) => (
|
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}>
|
<TouchableOpacity key={item.id} style={globalStyles.categoryItem}>
|
||||||
<View style={globalStyles.boxImageCategory}>
|
<View style={globalStyles.boxImageCategory}>
|
||||||
<Image
|
<Image
|
||||||
@@ -246,6 +282,604 @@ const BoxCategoryHome = () => {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
))}
|
))}
|
||||||
</View>
|
</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>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -253,33 +887,33 @@ const BoxCategoryHome = () => {
|
|||||||
export default HomeScreen;
|
export default HomeScreen;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
backgroundColor: "#fff",
|
|
||||||
},
|
|
||||||
homePage: {
|
homePage: {
|
||||||
backgroundColor: "#fff",
|
backgroundColor: "#fff",
|
||||||
},
|
},
|
||||||
slider: {
|
slider: {
|
||||||
width: winWidth,
|
width: winWidth - 20,
|
||||||
padding: 10,
|
overflow: "hidden",
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
height: ratio * 430,
|
margin: 10,
|
||||||
},
|
},
|
||||||
sliderSwipper: {
|
sliderSwipper: {
|
||||||
|
height: 210,
|
||||||
|
width: "100%",
|
||||||
|
overflow: "hidden",
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
},
|
},
|
||||||
imgContainer: {
|
imgContainer: {
|
||||||
width: winWidth,
|
width: "100%",
|
||||||
height: 220,
|
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
|
objectFit: "cover",
|
||||||
},
|
},
|
||||||
imgSlider: {
|
imgSlider: {
|
||||||
width: winWidth,
|
width: winWidth,
|
||||||
height: "100%",
|
height: "100%",
|
||||||
|
objectFit: "cover",
|
||||||
|
overflow: "hidden",
|
||||||
|
borderRadius: 10,
|
||||||
},
|
},
|
||||||
buttonNext: {
|
buttonNext: {
|
||||||
color: "#fff", // Màu chữ cho các nút chuyển
|
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
|
// src/styles/globalStyles.ts
|
||||||
import { StyleSheet, Dimensions } from 'react-native';
|
import { StyleSheet, Dimensions } from 'react-native';
|
||||||
var winWidth = Dimensions.get("window").width;
|
var winWidth = Dimensions.get("window").width;
|
||||||
|
const itemWidth = (winWidth - 40) / 4;
|
||||||
|
|
||||||
export const globalStyles = StyleSheet.create({
|
export const globalStyles = StyleSheet.create({
|
||||||
boxProductReviewTop: {
|
boxProductReviewTop: {
|
||||||
@@ -50,7 +51,7 @@ export const globalStyles = StyleSheet.create({
|
|||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
marginLeft: -10,
|
gap: 10
|
||||||
},
|
},
|
||||||
moreAll: {
|
moreAll: {
|
||||||
width: 110,
|
width: 110,
|
||||||
@@ -80,9 +81,12 @@ export const globalStyles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
listCategoryBox: {
|
listCategoryBox: {
|
||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
|
padding: 10,
|
||||||
|
height: 300
|
||||||
},
|
},
|
||||||
categoryItem: {
|
categoryItem: {
|
||||||
width: '100%',
|
width: '25%',
|
||||||
|
marginBottom: 25
|
||||||
},
|
},
|
||||||
boxImageCategory: {
|
boxImageCategory: {
|
||||||
width: 70,
|
width: 70,
|
||||||
@@ -103,6 +107,283 @@ export const globalStyles = StyleSheet.create({
|
|||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
marginTop: 5,
|
marginTop: 5,
|
||||||
textAlign: 'center',
|
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,
|
"strict": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"forceConsistentCasingInFileNames": true
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"baseUrl": "src",
|
||||||
|
"paths": {
|
||||||
|
"@components/*": ["components/*"],
|
||||||
|
"@layouts/*": ["layouts/*"],
|
||||||
|
"@screens/*": ["screens/*"],
|
||||||
|
"@assets/*": ["assets/*"],
|
||||||
|
"@navigation/*": ["navigation/*"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"include": ["src/**/*", "assets/**/*"]
|
"include": ["src/**/*", "assets/**/*"]
|
||||||
}
|
}
|
||||||
|
|||||||