Commit ecd23c3b authored by Syazmin's avatar Syazmin

Appointment Details and Listing Done

parent 7d9fc201
<?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="35" />
<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="35" />
<option name="brand" value="Lenovo" />
<option name="codename" value="TB330FU" />
<option name="formFactor" value="Tablet" />
<option name="id" value="TB330FU" />
<option name="labId" value="google" />
<option name="manufacturer" value="Lenovo" />
<option name="name" value="Tab M11" />
<option name="screenDensity" value="240" />
<option name="screenX" value="1200" />
<option name="screenY" value="1920" />
</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="36" />
<option name="brand" value="google" />
<option name="codename" value="blazer" />
<option name="id" value="blazer" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 10 Pro" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2410" />
</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="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="36" />
<option name="brand" value="google" />
<option name="codename" value="frankel" />
<option name="id" value="frankel" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 10" />
<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="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="35" />
<option name="brand" value="motorola" />
<option name="codename" value="kansas" />
<option name="id" value="kansas" />
<option name="labId" value="google" />
<option name="manufacturer" value="Motorola" />
<option name="name" value="moto g - 2025" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1604" />
</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="36" />
<option name="brand" value="google" />
<option name="codename" value="mustang" />
<option name="id" value="mustang" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 10 Pro XL" />
<option name="screenDensity" value="390" />
<option name="screenX" value="1080" />
<option name="screenY" value="2404" />
</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="36" />
<option name="brand" value="google" />
<option name="codename" value="rango" />
<option name="id" value="rango" />
<option name="labId" value="google" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 10 Pro Fold" />
<option name="screenDensity" value="390" />
<option name="screenX" value="2076" />
<option name="screenY" value="2152" />
</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="36" />
<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>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
......
{
"java.configuration.updateBuildConfiguration": "interactive"
}
\ No newline at end of file
......@@ -40,6 +40,7 @@ dependencies {
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.activity:activity:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
// Test implementation
testImplementation 'junit:junit:4.13.2'
......
......@@ -27,6 +27,12 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- NEW: Appointment List Activity -->
<activity
android:name=".AppointmentListActivity"
android:exported="false"
android:label="Appointments" />
</application>
</manifest>
\ No newline at end of file
package com.example.qmsmakeappointment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class AppointmentAdapterNew extends RecyclerView.Adapter<AppointmentAdapterNew.ViewHolder> {
private List<AppointmentEntity> appointments = new ArrayList<>();
private final OnAppointmentClickListener listener;
private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy", Locale.getDefault());
public interface OnAppointmentClickListener {
void onAppointmentClick(AppointmentEntity appointment);
}
public AppointmentAdapterNew(OnAppointmentClickListener listener) {
this.listener = listener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_appointment_new, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
AppointmentEntity appointment = appointments.get(position);
// Show date header only if it's a different date from previous item
if (position == 0 || !isSameDate(appointments.get(position - 1), appointment)) {
holder.dateHeader.setVisibility(View.VISIBLE);
LocalDate date = LocalDate.ofEpochDay(appointment.getSelectedDate());
holder.dateHeader.setText(date.format(dateFormatter));
} else {
holder.dateHeader.setVisibility(View.GONE);
}
// Set time
holder.time.setText(appointment.getSelectedTime());
// Set unit number
holder.unit.setText(appointment.getUnitNo());
// Set owner name (representative name from form)
String ownerName = appointment.getRepresentativeName();
if (ownerName != null && !ownerName.isEmpty()) {
holder.location.setText(ownerName);
} else {
holder.location.setText("No owner name");
}
// Set type badge
String type = appointment.getAppointmentType();
holder.typeBadge.setText(type);
// Set badge background based on type
if (type.equals("Handover")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_handover);
} else if (type.equals("Rectification")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_rectification);
} else if (type.equals("Joint Inspection")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_joint_inspection);
} else if (type.equals("Viewing")) {
holder.typeBadge.setBackgroundResource(R.drawable.badge_confirmed);
} else {
holder.typeBadge.setBackgroundResource(R.drawable.badge_handover);
}
// Click listener
holder.itemView.setOnClickListener(v -> listener.onAppointmentClick(appointment));
}
@Override
public int getItemCount() {
return appointments.size();
}
public void setAppointments(List<AppointmentEntity> appointments) {
this.appointments = appointments;
notifyDataSetChanged();
}
private boolean isSameDate(AppointmentEntity a1, AppointmentEntity a2) {
return a1.getSelectedDate() == a2.getSelectedDate();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView dateHeader;
TextView time;
TextView unit;
TextView typeBadge;
TextView location;
ViewHolder(View itemView) {
super(itemView);
dateHeader = itemView.findViewById(R.id.date_header);
time = itemView.findViewById(R.id.appointment_time);
unit = itemView.findViewById(R.id.appointment_unit);
typeBadge = itemView.findViewById(R.id.appointment_type_badge);
location = itemView.findViewById(R.id.appointment_location);
}
}
}
package com.example.qmsmakeappointment;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
......@@ -14,7 +15,30 @@ public interface AppointmentDao {
@Update
void updateAppointment(AppointmentEntity appointment);
@Delete
void deleteAppointment(AppointmentEntity appointment);
@Query("SELECT * FROM appointments ORDER BY selectedDate DESC")
List<AppointmentEntity> getAllAppointments();
// NEW QUERIES FOR APPOINTMENT LISTING
@Query("SELECT * FROM appointments WHERE appointmentType = :type ORDER BY selectedDate DESC")
List<AppointmentEntity> getAppointmentsByType(String type);
@Query("SELECT * FROM appointments WHERE selectedDate >= :currentDate ORDER BY selectedDate ASC")
List<AppointmentEntity> getUpcomingAppointments(long currentDate);
@Query("SELECT * FROM appointments WHERE selectedDate < :currentDate ORDER BY selectedDate DESC")
List<AppointmentEntity> getHistoryAppointments(long currentDate);
@Query("SELECT * FROM appointments WHERE id = :appointmentId")
AppointmentEntity getAppointmentById(int appointmentId);
@Query("UPDATE appointments SET status = :status WHERE id = :appointmentId")
void updateAppointmentStatus(int appointmentId, String status);
@Query("SELECT * FROM appointments WHERE status = :status ORDER BY selectedDate DESC")
List<AppointmentEntity> getAppointmentsByStatus(String status);
}
......@@ -6,7 +6,7 @@ import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
@Database(entities = {AppointmentEntity.class}, version = 1, exportSchema = false)
@Database(entities = {AppointmentEntity.class}, version = 2, exportSchema = false)
public abstract class AppointmentDatabase extends RoomDatabase {
public abstract AppointmentDao appointmentDao();
......@@ -19,6 +19,7 @@ public abstract class AppointmentDatabase extends RoomDatabase {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppointmentDatabase.class, "appointment_database")
.fallbackToDestructiveMigration() // Allow destructive migration for now
.build();
}
}
......
package com.example.qmsmakeappointment;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AppointmentDetailsFragment extends Fragment {
private static final String ARG_APPOINTMENT_ID = "appointment_id";
private int appointmentId;
private AppointmentEntity appointment;
private AppointmentDatabase db;
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
// UI Components
private TextView detailsUnitNo;
private TextView detailsTypeBadge, detailsDateValue, detailsTimeValue;
private TextView detailsLocationValue, locateButton, viewTermsButton;
private TextView detailsOwnerName, detailsOwnerNric, detailsOwnerContact;
private Button tabSummary, tabOwnerInfo;
private LinearLayout summaryContent, ownerInfoContent;
private Button addToCalendarButton, cancelAppointmentButton;
public static AppointmentDetailsFragment newInstance(int appointmentId) {
AppointmentDetailsFragment fragment = new AppointmentDetailsFragment();
Bundle args = new Bundle();
args.putInt(ARG_APPOINTMENT_ID, appointmentId);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
appointmentId = getArguments().getInt(ARG_APPOINTMENT_ID);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_appointment_details, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Initialize database
db = AppointmentDatabase.getDatabase(requireContext());
// Initialize views
detailsUnitNo = view.findViewById(R.id.details_unit_no);
detailsTypeBadge = view.findViewById(R.id.details_type_badge);
detailsDateValue = view.findViewById(R.id.details_date_value);
detailsTimeValue = view.findViewById(R.id.details_time_value);
detailsLocationValue = view.findViewById(R.id.details_location_value);
locateButton = view.findViewById(R.id.locate_button);
viewTermsButton = view.findViewById(R.id.view_terms_button);
detailsOwnerName = view.findViewById(R.id.details_owner_name);
detailsOwnerNric = view.findViewById(R.id.details_owner_nric);
detailsOwnerContact = view.findViewById(R.id.details_owner_contact);
tabSummary = view.findViewById(R.id.tab_summary);
tabOwnerInfo = view.findViewById(R.id.tab_owner_info);
summaryContent = view.findViewById(R.id.summary_content);
ownerInfoContent = view.findViewById(R.id.owner_info_content);
addToCalendarButton = view.findViewById(R.id.add_to_calendar_button);
cancelAppointmentButton = view.findViewById(R.id.cancel_appointment_button);
// Tab click listeners
tabSummary.setOnClickListener(v -> showSummaryTab());
tabOwnerInfo.setOnClickListener(v -> showOwnerInfoTab());
// Load appointment details
loadAppointmentDetails();
// Add to Calendar button
addToCalendarButton.setOnClickListener(v -> addToCalendar());
// Cancel Appointment button
cancelAppointmentButton.setOnClickListener(v -> showCancelConfirmationDialog());
// Locate button
locateButton.setOnClickListener(v -> {
// TODO: Open map with location
Toast.makeText(getContext(), "Opening location...", Toast.LENGTH_SHORT).show();
});
// View Terms button
viewTermsButton.setOnClickListener(v -> {
showTermsAndConditionsDialog();
});
}
private void showTermsAndConditionsDialog() {
// Create a dialog
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
// Inflate custom layout for terms and conditions
View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_terms_conditions, null);
builder.setView(dialogView);
builder.setPositiveButton("Close", (dialog, which) -> dialog.dismiss());
AlertDialog dialog = builder.create();
dialog.show();
}
private void showSummaryTab() {
// Update tab appearance
tabSummary.setBackgroundTintList(android.content.res.ColorStateList.valueOf(
androidx.core.content.ContextCompat.getColor(requireContext(), R.color.colorPrimary)));
tabSummary.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), android.R.color.white));
tabOwnerInfo.setBackgroundTintList(android.content.res.ColorStateList.valueOf(
androidx.core.content.ContextCompat.getColor(requireContext(), android.R.color.white)));
tabOwnerInfo.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.colorPrimary));
// Show/hide content
summaryContent.setVisibility(View.VISIBLE);
ownerInfoContent.setVisibility(View.GONE);
}
private void showOwnerInfoTab() {
// Update tab appearance
tabOwnerInfo.setBackgroundTintList(android.content.res.ColorStateList.valueOf(
androidx.core.content.ContextCompat.getColor(requireContext(), R.color.colorPrimary)));
tabOwnerInfo.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), android.R.color.white));
tabSummary.setBackgroundTintList(android.content.res.ColorStateList.valueOf(
androidx.core.content.ContextCompat.getColor(requireContext(), android.R.color.white)));
tabSummary.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.colorPrimary));
// Show/hide content
summaryContent.setVisibility(View.GONE);
ownerInfoContent.setVisibility(View.VISIBLE);
}
private void loadAppointmentDetails() {
executorService.execute(() -> {
appointment = db.appointmentDao().getAppointmentById(appointmentId);
if (appointment != null) {
requireActivity().runOnUiThread(() -> displayAppointmentDetails());
} else {
requireActivity().runOnUiThread(() -> {
Toast.makeText(getContext(), "Appointment not found", Toast.LENGTH_SHORT).show();
requireActivity().getSupportFragmentManager().popBackStack();
});
}
});
}
private void displayAppointmentDetails() {
// Unit Number
detailsUnitNo.setText(appointment.getUnitNo());
// Type Badge
detailsTypeBadge.setText(appointment.getAppointmentType());
switch (appointment.getAppointmentType()) {
case "Handover":
detailsTypeBadge.setBackgroundResource(R.drawable.badge_handover);
break;
case "Rectification":
detailsTypeBadge.setBackgroundResource(R.drawable.badge_rectification);
break;
case "Joint Inspection":
detailsTypeBadge.setBackgroundResource(R.drawable.badge_joint_inspection);
break;
case "Viewing":
detailsTypeBadge.setBackgroundResource(R.drawable.badge_confirmed);
break;
default:
detailsTypeBadge.setBackgroundResource(R.drawable.badge_handover);
break;
}
// Date
LocalDate date = LocalDate.ofEpochDay(appointment.getSelectedDate());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMM yyyy", Locale.getDefault());
detailsDateValue.setText(date.format(formatter));
// Time
detailsTimeValue.setText(appointment.getSelectedTime());
// Location (use actual location from database)
detailsLocationValue.setText(appointment.getLocation());
// Owner Info (using representative data for now)
if (appointment.getRepresentativeName() != null && !appointment.getRepresentativeName().isEmpty()) {
detailsOwnerName.setText(appointment.getRepresentativeName());
} else {
detailsOwnerName.setText("John Anthony Snow");
}
// NRIC (placeholder)
detailsOwnerNric.setText("951109057718");
// Contact
if (appointment.getContactNumber() != null && !appointment.getContactNumber().isEmpty()) {
detailsOwnerContact.setText(appointment.getContactNumber());
} else {
detailsOwnerContact.setText("+60178006540");
}
// Hide "Add to Calendar" and "Cancel" for past or cancelled appointments
long currentDate = LocalDate.now().toEpochDay();
if (appointment.getSelectedDate() < currentDate || "Cancelled".equals(appointment.getStatus())) {
addToCalendarButton.setVisibility(View.GONE);
}
if ("Cancelled".equals(appointment.getStatus()) || "Completed".equals(appointment.getStatus())) {
cancelAppointmentButton.setVisibility(View.GONE);
}
}
private void addToCalendar() {
if (appointment == null) return;
try {
// Convert epoch day to milliseconds
LocalDate appointmentDate = LocalDate.ofEpochDay(appointment.getSelectedDate());
long startMillis = appointmentDate.atStartOfDay().toEpochSecond(java.time.ZoneOffset.UTC) * 1000;
Intent intent = new Intent(Intent.ACTION_INSERT)
.setData(CalendarContract.Events.CONTENT_URI)
.putExtra(CalendarContract.Events.TITLE, appointment.getAppointmentType() + " - " + appointment.getUnitNo())
.putExtra(CalendarContract.Events.DESCRIPTION, "Location: " + appointment.getLocation())
.putExtra(CalendarContract.Events.EVENT_LOCATION, appointment.getLocation())
.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis)
.putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, false);
startActivity(intent);
} catch (Exception e) {
Toast.makeText(getContext(), "Unable to open calendar", Toast.LENGTH_SHORT).show();
}
}
private void showCancelConfirmationDialog() {
new AlertDialog.Builder(requireContext())
.setTitle("Cancel Appointment")
.setMessage("Are you sure you want to cancel this appointment?")
.setPositiveButton("Yes", (dialog, which) -> cancelAppointment())
.setNegativeButton("No", null)
.show();
}
private void cancelAppointment() {
executorService.execute(() -> {
db.appointmentDao().updateAppointmentStatus(appointmentId, "Cancelled");
requireActivity().runOnUiThread(() -> {
Toast.makeText(getContext(), "Appointment cancelled", Toast.LENGTH_SHORT).show();
// Refresh the details
loadAppointmentDetails();
// Or go back to list
// requireActivity().getSupportFragmentManager().popBackStack();
});
});
}
@Override
public void onDestroy() {
super.onDestroy();
executorService.shutdown();
}
}
......@@ -17,6 +17,12 @@ public class AppointmentEntity {
private String contactEmail;
private String contactNumber;
private String attachmentPath;
// for Appointment Listing
private String appointmentType;
private String status;
private String location;
private long createdTimestamp;
public AppointmentEntity(String unitNo, long selectedDate, String selectedTime, String representativeName, String contactEmail, String contactNumber, String attachmentPath) {
this.unitNo = unitNo;
......@@ -26,6 +32,12 @@ public class AppointmentEntity {
this.contactEmail = contactEmail;
this.contactNumber = contactNumber;
this.attachmentPath = attachmentPath;
// Set default values for new fields
this.appointmentType = "Handover"; // Default type
this.status = "Confirmed"; // Default status
this.location = "A2-1-2, Block A, Ashlar Residence, 63105, Selangor"; // Default location
this.createdTimestamp = System.currentTimeMillis(); // Current time
}
// Getters and setters (Required for room)
......@@ -46,4 +58,14 @@ public class AppointmentEntity {
public String getAttachmentPath() { return attachmentPath; }
public void setAttachmentPath(String attachmentPath) { this.attachmentPath = attachmentPath; }
// NEW GETTERS AND SETTERS
public String getAppointmentType() { return appointmentType; }
public void setAppointmentType(String appointmentType) { this.appointmentType = appointmentType; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getLocation() { return location; }
public void setLocation(String location) { this.location = location; }
public long getCreatedTimestamp() { return createdTimestamp; }
public void setCreatedTimestamp(long createdTimestamp) { this.createdTimestamp = createdTimestamp; }
}
package com.example.qmsmakeappointment;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.RadioGroup;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.bottomsheet.BottomSheetDialog;
public class AppointmentListActivity extends AppCompatActivity {
private ImageButton backButton;
private ImageButton filterButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_appointment_list);
backButton = findViewById(R.id.back_button);
filterButton = findViewById(R.id.filter_button);
// Load the appointment list fragment
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container_list, new AppointmentListFragmentNew())
.commit();
}
// Back button - handle fragment back stack or close activity
backButton.setOnClickListener(v -> {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
// If there are fragments in the back stack, pop them
getSupportFragmentManager().popBackStack();
} else {
// Otherwise, close the activity
finish();
}
});
// Filter button - Can be used for additional sorting options if needed
filterButton.setOnClickListener(v -> showFilterDialog());
}
private void showFilterDialog() {
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(this);
View dialogView = getLayoutInflater().inflate(R.layout.bottom_sheet_filter, null);
bottomSheetDialog.setContentView(dialogView);
// Get radio groups
RadioGroup radioGroupSort = dialogView.findViewById(R.id.radio_group_sort);
RadioGroup radioGroupType = dialogView.findViewById(R.id.radio_group_type);
RadioGroup radioGroupStatus = dialogView.findViewById(R.id.radio_group_status);
// Get buttons
Button btnReset = dialogView.findViewById(R.id.btn_reset_filter);
Button btnApply = dialogView.findViewById(R.id.btn_apply_filter);
// Reset button - reset all to default
btnReset.setOnClickListener(v -> {
radioGroupSort.check(R.id.radio_newest_first);
radioGroupType.check(R.id.radio_all_types);
radioGroupStatus.check(R.id.radio_all_status);
});
// Apply button - apply filter to the list fragment
btnApply.setOnClickListener(v -> {
int sortId = radioGroupSort.getCheckedRadioButtonId();
int typeId = radioGroupType.getCheckedRadioButtonId();
int statusId = radioGroupStatus.getCheckedRadioButtonId();
// Get the fragment
AppointmentListFragmentNew fragment = (AppointmentListFragmentNew) getSupportFragmentManager()
.findFragmentById(R.id.fragment_container_list);
if (fragment != null) {
// Determine sort order
String sortOrder = "newest";
if (sortId == R.id.radio_oldest_first) sortOrder = "oldest";
else if (sortId == R.id.radio_date_ascending) sortOrder = "date_asc";
else if (sortId == R.id.radio_date_descending) sortOrder = "date_desc";
// Determine type filter
String typeFilter = null;
if (typeId == R.id.radio_handover_only) typeFilter = "Handover";
else if (typeId == R.id.radio_viewing_only) typeFilter = "Viewing";
// Determine status filter
String statusFilter = null;
if (statusId == R.id.radio_confirmed_only) statusFilter = "Confirmed";
else if (statusId == R.id.radio_cancelled_only) statusFilter = "Cancelled";
else if (statusId == R.id.radio_completed_only) statusFilter = "Completed";
// Apply filter
fragment.applyFilter(sortOrder, typeFilter, statusFilter);
}
bottomSheetDialog.dismiss();
});
bottomSheetDialog.show();
}
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
// If there are fragments in the back stack, pop them
getSupportFragmentManager().popBackStack();
} else {
// Otherwise, use default back behavior
try {
super.onBackPressed();
} catch (Exception e) {
finish();
}
}
}
}
package com.example.qmsmakeappointment;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.textfield.TextInputEditText;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AppointmentListFragmentNew extends Fragment {
private RecyclerView recyclerView;
private AppointmentAdapterNew adapter;
private FloatingActionButton fabAddAppointment;
private SwipeRefreshLayout swipeRefresh;
private AutoCompleteTextView typeFilterDropdown;
private AutoCompleteTextView statusFilterDropdown;
private TextInputEditText searchInput;
private AppointmentDatabase db;
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
private List<AppointmentEntity> allAppointments = new ArrayList<>();
private String currentTypeFilter = "All Type";
private String currentStatusFilter = "Upcoming";
private static final String STATE_TYPE_FILTER = "type_filter";
private static final String STATE_STATUS_FILTER = "status_filter";
private static final String STATE_SEARCH_TEXT = "search_text";
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_appointment_list, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Restore saved state
if (savedInstanceState != null) {
currentTypeFilter = savedInstanceState.getString(STATE_TYPE_FILTER, "All Type");
currentStatusFilter = savedInstanceState.getString(STATE_STATUS_FILTER, "Upcoming");
}
// Initialize database
db = AppointmentDatabase.getDatabase(requireContext());
// Initialize views
recyclerView = view.findViewById(R.id.appointments_recycler_view);
fabAddAppointment = view.findViewById(R.id.fab_add_appointment);
swipeRefresh = view.findViewById(R.id.swipe_refresh);
typeFilterDropdown = view.findViewById(R.id.type_filter_dropdown);
statusFilterDropdown = view.findViewById(R.id.status_filter_dropdown);
searchInput = view.findViewById(R.id.search_input);
// Setup type filter dropdown
String[] typeOptions = {"All Type", "Handover", "Rectification", "Joint Inspection", "Viewing"};
ArrayAdapter<String> typeAdapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_dropdown_item_1line, typeOptions);
typeFilterDropdown.setAdapter(typeAdapter);
typeFilterDropdown.setText(currentTypeFilter, false);
typeFilterDropdown.setThreshold(1000); // Prevent filtering, always show all items
typeFilterDropdown.setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
typeFilterDropdown.showDropDown();
}
});
typeFilterDropdown.setOnClickListener(v -> {
typeFilterDropdown.showDropDown();
});
typeFilterDropdown.setOnItemClickListener((parent, v, position, id) -> {
currentTypeFilter = typeOptions[position];
typeFilterDropdown.clearFocus();
filterAndDisplayAppointments();
});
// Setup status filter dropdown
String[] statusOptions = {"All", "Upcoming", "Completed", "Cancelled"};
ArrayAdapter<String> statusAdapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_dropdown_item_1line, statusOptions);
statusFilterDropdown.setAdapter(statusAdapter);
statusFilterDropdown.setText(currentStatusFilter, false);
statusFilterDropdown.setThreshold(1000); // Prevent filtering, always show all items
statusFilterDropdown.setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
statusFilterDropdown.showDropDown();
}
});
statusFilterDropdown.setOnClickListener(v -> {
statusFilterDropdown.showDropDown();
});
statusFilterDropdown.setOnItemClickListener((parent, v, position, id) -> {
currentStatusFilter = statusOptions[position];
statusFilterDropdown.clearFocus();
filterAndDisplayAppointments();
});
// Setup search
searchInput.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
filterAndDisplayAppointments();
}
@Override
public void afterTextChanged(Editable s) {}
});
// Setup SwipeRefreshLayout
swipeRefresh.setColorSchemeResources(R.color.colorPrimary);
swipeRefresh.setOnRefreshListener(this::loadAllAppointments);
// Setup RecyclerView
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
adapter = new AppointmentAdapterNew(appointment -> {
// Handle appointment click - navigate to details
AppointmentDetailsFragment detailsFragment = AppointmentDetailsFragment.newInstance(appointment.getId());
requireActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container_list, detailsFragment)
.addToBackStack(null)
.commit();
});
recyclerView.setAdapter(adapter);
// FAB to create new appointment
fabAddAppointment.setOnClickListener(v -> {
Intent intent = new Intent(getActivity(), MainActivity.class);
startActivity(intent);
});
// Load appointments
loadAllAppointments();
}
private void loadAllAppointments() {
executorService.execute(() -> {
List<AppointmentEntity> appointments = db.appointmentDao().getAllAppointments();
requireActivity().runOnUiThread(() -> {
allAppointments = appointments;
filterAndDisplayAppointments();
swipeRefresh.setRefreshing(false);
});
});
}
private void filterAndDisplayAppointments() {
List<AppointmentEntity> filtered = new ArrayList<>(allAppointments);
// Filter by type
if (!currentTypeFilter.equals("All Type")) {
filtered.removeIf(appointment -> !appointment.getAppointmentType().equals(currentTypeFilter));
}
// Filter by status
long currentDate = LocalDate.now().toEpochDay();
if (currentStatusFilter.equals("Upcoming")) {
// Show only future appointments that are not cancelled
filtered.removeIf(appointment ->
appointment.getSelectedDate() < currentDate ||
appointment.getStatus().equals("Cancelled"));
} else if (currentStatusFilter.equals("Completed")) {
// Show only completed appointments
filtered.removeIf(appointment -> !appointment.getStatus().equals("Completed"));
} else if (currentStatusFilter.equals("Cancelled")) {
// Show only cancelled appointments
filtered.removeIf(appointment -> !appointment.getStatus().equals("Cancelled"));
}
// If "All", don't filter by status - show everything
// Filter by search text
String searchText = searchInput.getText().toString().trim().toLowerCase();
if (!searchText.isEmpty()) {
filtered.removeIf(appointment ->
!appointment.getUnitNo().toLowerCase().contains(searchText) &&
!appointment.getLocation().toLowerCase().contains(searchText)
);
}
// Sort by date, then by time
Collections.sort(filtered, Comparator
.comparingLong(AppointmentEntity::getSelectedDate)
.thenComparing(AppointmentEntity::getSelectedTime));
adapter.setAppointments(filtered);
}
// Public method called from Activity's filter dialog
public void applyFilter(String sortOrder, String typeFilter, String statusFilter) {
// This method can be used for additional sorting from the filter button
// For now, the dropdowns handle most filtering
// You can extend this if needed
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(STATE_TYPE_FILTER, currentTypeFilter);
outState.putString(STATE_STATUS_FILTER, currentStatusFilter);
if (searchInput != null) {
outState.putString(STATE_SEARCH_TEXT, searchInput.getText().toString());
}
}
@Override
public void onResume() {
super.onResume();
// Restore dropdown values when returning to this fragment
if (typeFilterDropdown != null && statusFilterDropdown != null) {
typeFilterDropdown.setText(currentTypeFilter, false);
statusFilterDropdown.setText(currentStatusFilter, false);
}
loadAllAppointments();
}
@Override
public void onDestroy() {
super.onDestroy();
executorService.shutdown();
}
}
......@@ -14,6 +14,7 @@ public class AppointmentViewModel extends ViewModel {
private final MutableLiveData<String> contactEmail = new MutableLiveData<>();
private final MutableLiveData<String> contactNumber = new MutableLiveData<>();
private final MutableLiveData<Boolean> isRepresentativeAttending = new MutableLiveData<>(false);
private final MutableLiveData<String> appointmentType = new MutableLiveData<>("Handover"); // Default to Handover
// Getters
public LiveData<String> getUnitNo() { return unitNo; }
......@@ -23,6 +24,7 @@ public class AppointmentViewModel extends ViewModel {
public LiveData<String> getContactEmail() { return contactEmail; }
public LiveData<String> getContactNumber() { return contactNumber; }
public LiveData<Boolean> isRepresentativeAttending() { return isRepresentativeAttending; }
public LiveData<String> getAppointmentType() { return appointmentType; }
// Setters
public void setSelectedDate(long date) { selectedDate.setValue(date); }
......@@ -31,6 +33,7 @@ public class AppointmentViewModel extends ViewModel {
public void setContactEmail(String email) { contactEmail.setValue(email); }
public void setContactNumber(String number) { contactNumber.setValue(number); }
public void setRepresentativeAttending(boolean isAttending) { isRepresentativeAttending.setValue(isAttending); }
public void setAppointmentType(String type) { appointmentType.setValue(type); }
public void clearRepresentativeData() {
representativeName.setValue(null);
......@@ -43,6 +46,7 @@ public class AppointmentViewModel extends ViewModel {
selectedDate.setValue(null);
selectedTime.setValue(null);
isRepresentativeAttending.setValue(false);
appointmentType.setValue("Handover"); // Reset to default
clearRepresentativeData();
}
}
package com.example.qmsmakeappointment;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageButton;
import android.widget.Toast;
......@@ -97,6 +98,11 @@ public class MainActivity extends AppCompatActivity {
viewModel.getContactNumber().getValue(),
null // Placeholder for attachment path
);
// Set the appointment type from ViewModel
if (viewModel.getAppointmentType().getValue() != null) {
newAppointment.setAppointmentType(viewModel.getAppointmentType().getValue());
}
// Run database insert on a background thread
executorService.execute(() -> {
......@@ -104,13 +110,16 @@ public class MainActivity extends AppCompatActivity {
// Post success back to the main thread
runOnUiThread(() -> {
// Show Access Alert
Toast.makeText(MainActivity.this, "Success: You have successfully made a appointment.", Toast.LENGTH_LONG).show();
// Clear back stack and restart to Terms & Conditions
// Clear back stack and reset ViewModel
getSupportFragmentManager().popBackStack(null, androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE);
viewModel.resetAppointment();
loadFragment(new TermsConditionsFragment(), false);
// Navigate to Appointment List Activity
Intent intent = new Intent(MainActivity.this, AppointmentListActivity.class);
startActivity(intent);
// Optionally finish this activity
finish();
});
});
}
......
package com.example.qmsmakeappointment;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.card.MaterialCardView;
public class Step0TypeFragment extends Fragment {
private AppointmentViewModel viewModel;
private MaterialCardView cardHandover, cardRectification, cardJointInspection, cardViewing;
private Button nextButton;
private String selectedType = null;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_step_0_type, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewModel = new ViewModelProvider(requireActivity()).get(AppointmentViewModel.class);
// Initialize views
cardHandover = view.findViewById(R.id.card_handover);
cardRectification = view.findViewById(R.id.card_rectification);
cardJointInspection = view.findViewById(R.id.card_joint_inspection);
cardViewing = view.findViewById(R.id.card_viewing);
nextButton = view.findViewById(R.id.next_button);
// Check if type was already selected (if user comes back)
if (viewModel.getAppointmentType().getValue() != null) {
selectedType = viewModel.getAppointmentType().getValue();
updateCardSelection();
enableNextButton();
}
// Set click listeners for cards
cardHandover.setOnClickListener(v -> selectType("Handover", cardHandover));
cardRectification.setOnClickListener(v -> selectType("Rectification", cardRectification));
cardJointInspection.setOnClickListener(v -> selectType("Joint Inspection", cardJointInspection));
cardViewing.setOnClickListener(v -> selectType("Viewing", cardViewing));
// Next button click listener
nextButton.setOnClickListener(v -> {
if (selectedType != null) {
viewModel.setAppointmentType(selectedType);
((MainActivity) requireActivity()).loadFragment(new Step1DateFragment(), true);
}
});
}
private void selectType(String type, MaterialCardView selectedCard) {
selectedType = type;
// Reset all cards
resetAllCards();
// Highlight selected card
int tealColor = ContextCompat.getColor(requireContext(), R.color.colorPrimary);
selectedCard.setStrokeColor(tealColor);
// Enable next button
enableNextButton();
}
private void resetAllCards() {
int transparentColor = ContextCompat.getColor(requireContext(), android.R.color.transparent);
cardHandover.setStrokeColor(transparentColor);
cardRectification.setStrokeColor(transparentColor);
cardJointInspection.setStrokeColor(transparentColor);
cardViewing.setStrokeColor(transparentColor);
}
private void updateCardSelection() {
resetAllCards();
int tealColor = ContextCompat.getColor(requireContext(), R.color.colorPrimary);
if ("Handover".equals(selectedType)) {
cardHandover.setStrokeColor(tealColor);
} else if ("Rectification".equals(selectedType)) {
cardRectification.setStrokeColor(tealColor);
} else if ("Joint Inspection".equals(selectedType)) {
cardJointInspection.setStrokeColor(tealColor);
} else if ("Viewing".equals(selectedType)) {
cardViewing.setStrokeColor(tealColor);
}
}
private void enableNextButton() {
nextButton.setEnabled(true);
int tealColor = ContextCompat.getColor(requireContext(), R.color.colorPrimary);
nextButton.setBackgroundTintList(ColorStateList.valueOf(tealColor));
}
}
......@@ -44,9 +44,9 @@ public class TermsConditionsFragment extends Fragment {
// Handle Agree and Next button click
agreeNextButton.setOnClickListener(v -> {
// Navigate to Step 1
// Navigate to appointment type selection step
if (getActivity() instanceof MainActivity) {
((MainActivity) getActivity()).loadFragment(new Step1DateFragment(), false);
((MainActivity) getActivity()).loadFragment(new Step0TypeFragment(), false);
}
});
}
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FF5252" />
<corners android:radius="12dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#9E9E9E" />
<corners android:radius="12dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4CAF50" />
<corners android:radius="12dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/colorPrimary" />
<corners android:radius="12dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#D32F2F"/>
<corners android:radius="12dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FF6B35"/>
<corners android:radius="12dp"/>
</shape>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="64"
android:viewportHeight="64">
<!-- Background -->
<path
android:fillColor="#F8F8F8"
android:pathData="M4,4 L60,4 L60,60 L4,60 Z"/>
<!-- Main building outline -->
<path
android:strokeColor="#333333"
android:strokeWidth="2"
android:fillColor="#00000000"
android:pathData="M12,12 L52,12 L52,52 L12,52 Z"/>
<!-- Vertical room divider (left) -->
<path
android:strokeColor="#666666"
android:strokeWidth="1.5"
android:pathData="M24,12 L24,52"/>
<!-- Vertical room divider (right) -->
<path
android:strokeColor="#666666"
android:strokeWidth="1.5"
android:pathData="M40,12 L40,52"/>
<!-- Horizontal divider (upper) -->
<path
android:strokeColor="#666666"
android:strokeWidth="1.5"
android:pathData="M12,26 L52,26"/>
<!-- Horizontal divider (lower) -->
<path
android:strokeColor="#666666"
android:strokeWidth="1.5"
android:pathData="M12,38 L52,38"/>
<!-- Door symbol -->
<path
android:strokeColor="#0E7392"
android:strokeWidth="2"
android:pathData="M28,52 L28,46 L34,46 L34,52"/>
<!-- Window symbols -->
<path
android:strokeColor="#999999"
android:strokeWidth="1.5"
android:pathData="M16,16 L20,16"/>
<path
android:strokeColor="#999999"
android:strokeWidth="1.5"
android:pathData="M44,16 L48,16"/>
<!-- Stairs indicator -->
<path
android:strokeColor="#999999"
android:strokeWidth="1"
android:pathData="M30,20 L34,20 M30,22 L34,22 M30,24 L34,24"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Toolbar -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:background="@color/colorPrimary"
app:layout_constraintTop_toTopOf="parent">
<ImageButton
android:id="@+id/back_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="8dp"
android:background="@null"
android:contentDescription="Back"
android:src="@drawable/ic_chevron_left"
app:tint="@color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Appointment"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<ImageButton
android:id="@+id/filter_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="8dp"
android:background="@null"
android:contentDescription="Filter"
android:src="@android:drawable/ic_menu_sort_by_size"
app:tint="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- Fragment Container -->
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_list"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/toolbar_layout"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@android:color/white">
<!-- Handle bar -->
<View
android:layout_width="40dp"
android:layout_height="4dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:background="#CCCCCC"
android:backgroundTint="#DDDDDD" />
<!-- Title -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Filter &amp; Sort"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp" />
<!-- Scrollable Content -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:maxHeight="400dp"
android:paddingHorizontal="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Sort By Section -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sort By"
android:textSize="14sp"
android:textStyle="bold"
android:textColor="#666666"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp" />
<RadioGroup
android:id="@+id/radio_group_sort"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_newest_first"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Newest First"
android:textSize="16sp"
android:paddingVertical="8dp"
android:checked="true" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_oldest_first"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Oldest First"
android:textSize="16sp"
android:paddingVertical="8dp" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_date_ascending"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Appointment Date (Earliest)"
android:textSize="16sp"
android:paddingVertical="8dp" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_date_descending"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Appointment Date (Latest)"
android:textSize="16sp"
android:paddingVertical="8dp" />
</RadioGroup>
<!-- Divider -->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginVertical="16dp"
android:background="#EEEEEE" />
<!-- Filter By Type Section -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Filter By Type"
android:textSize="14sp"
android:textStyle="bold"
android:textColor="#666666"
android:layout_marginBottom="8dp" />
<RadioGroup
android:id="@+id/radio_group_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_all_types"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="All Types"
android:textSize="16sp"
android:paddingVertical="8dp"
android:checked="true" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_handover_only"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Handover Only"
android:textSize="16sp"
android:paddingVertical="8dp" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_viewing_only"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Viewing Only"
android:textSize="16sp"
android:paddingVertical="8dp" />
</RadioGroup>
<!-- Divider -->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginVertical="16dp"
android:background="#EEEEEE" />
<!-- Filter By Status Section -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Filter By Status"
android:textSize="14sp"
android:textStyle="bold"
android:textColor="#666666"
android:layout_marginBottom="8dp" />
<RadioGroup
android:id="@+id/radio_group_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_all_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="All Status"
android:textSize="16sp"
android:paddingVertical="8dp"
android:checked="true" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_confirmed_only"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Confirmed Only"
android:textSize="16sp"
android:paddingVertical="8dp" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_cancelled_only"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Cancelled Only"
android:textSize="16sp"
android:paddingVertical="8dp" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/radio_completed_only"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Completed Only"
android:textSize="16sp"
android:paddingVertical="8dp" />
</RadioGroup>
</LinearLayout>
</ScrollView>
<!-- Buttons (Fixed at bottom, always visible) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:paddingBottom="24dp"
android:orientation="horizontal"
android:gravity="center"
android:background="@android:color/white"
android:elevation="4dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_reset_filter"
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:text="Reset"
android:textSize="14sp"
android:textAllCaps="false"
style="@style/Widget.Material3.Button.OutlinedButton"
app:strokeColor="@color/colorPrimary"
android:textColor="@color/colorPrimary" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_apply_filter"
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:text="Apply"
android:textSize="14sp"
android:textAllCaps="false"
android:backgroundTint="@color/colorPrimary"
android:textColor="@android:color/white" />
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp"
android:background="@android:color/white">
<!-- Icon -->
<ImageView
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center_horizontal"
android:src="@android:drawable/ic_dialog_alert"
android:tint="#FF5252"
android:contentDescription="Cancel Icon" />
<!-- Title -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:text="Cancel Appointment?"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="#000000" />
<!-- Message -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:text="Are you sure you want to cancel this appointment? This action cannot be undone."
android:textSize="14sp"
android:textColor="#666666"
android:gravity="center"
android:lineSpacingExtra="4dp" />
<!-- Buttons Container -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="horizontal"
android:gravity="center">
<!-- No Button -->
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_no"
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:text="No, Keep It"
android:textSize="14sp"
android:textAllCaps="false"
style="@style/Widget.Material3.Button.OutlinedButton"
app:strokeColor="@color/colorPrimary"
app:strokeWidth="1dp"
android:textColor="@color/colorPrimary" />
<!-- Yes Button -->
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_yes"
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:text="Yes, Cancel"
android:textSize="14sp"
android:textAllCaps="false"
android:backgroundTint="#FF5252"
android:textColor="@android:color/white" />
</LinearLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<!-- Title -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Terms &amp; Conditions"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="16dp"
android:gravity="center"/>
<!-- Scrollable Terms Content -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam aliquet tempor massa et ullamcorper. Nullam in pulvinar odio. Sed vitae neque ac neque bibendum bibendum at id felis. Morbi nec mi sagittis, malesuada ex vitae neque ac neque bibendum bibendum neque. Sed elementum tellus libero, sit amet tempus nibh. In porttitor congue sapien rhoncus ultrices placerat. Phasellus ut tempus orci euismod et. Curabitur ultrices tempus, viverra diam at, efficitur orci. Nullam porttitor, auctor at imperdiet. Cras porta semper felis. Fermentum ante interdum quis. Donec bibendum ultrices sapien at pretium. Donec fermentum fermentum dignissim. Maecenas accumsan a felis quis fermentum.\n\nDonec vitae accumsan metus. Etiam tempus vitae dui vel aliquam. Sed ac faucibus odio, eget vulputate nunc. Morbi posuere sem eros, et viverra justo porta sit amet. Cras in tempor metus, in aliquet justo. Praesent varius mi sapien, quis facilisis erat dictum ut. Cras consequat ligula quis interdum molestie.\n\nDonec a iaculis urna, eget hendrerit massa. Sed nec nunc id neque posuere pretium. Vivamus cursus id nibh eu justo. Aenean sed tincidunt nunc, in fringilla nibh. Fusce luctus interdum justo a molestie. Nunc accumsan orci vel lectus varius, nec rhoncus felis."
android:textSize="14sp"
android:textColor="@android:color/black"
android:lineSpacingExtra="4dp"/>
</ScrollView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/bottom_buttons_details">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Unit Number and Floor Plan Image -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="8dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="For Unit No. :"
android:textSize="12sp"
android:textColor="@color/Grey"/>
<TextView
android:id="@+id/details_unit_no"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A-3-11"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@android:color/black"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Type A"
android:textSize="12sp"
android:textColor="@color/Grey"/>
</LinearLayout>
<!-- Floor Plan Image -->
<ImageView
android:id="@+id/floor_plan_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@drawable/household"
android:scaleType="fitCenter"
android:contentDescription="Floor plan" />
</LinearLayout>
<!-- Tab Layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp">
<Button
android:id="@+id/tab_summary"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="Summary"
android:textColor="@android:color/white"
android:backgroundTint="@color/colorPrimary"
app:strokeWidth="0dp"
app:cornerRadius="24dp"
android:layout_marginEnd="8dp" />
<Button
android:id="@+id/tab_owner_info"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="Owner Info"
android:textColor="@color/colorPrimary"
android:backgroundTint="@android:color/white"
app:strokeColor="@color/colorPrimary"
app:strokeWidth="2dp"
app:cornerRadius="24dp"
android:layout_marginStart="8dp" />
</LinearLayout>
<!-- Summary Content (Initially Visible) -->
<LinearLayout
android:id="@+id/summary_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="visible">
<!-- Appointment Info Section -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Appointment Info"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="16dp"/>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeWidth="1dp"
app:strokeColor="#E0E0E0"
android:layout_marginBottom="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<!-- Type -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Type :"
android:textSize="14sp"
android:textColor="@color/Grey"/>
<TextView
android:id="@+id/details_type_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Handover"
android:textColor="@android:color/white"
android:textSize="12sp"
android:textStyle="bold"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:background="@drawable/badge_handover"/>
</LinearLayout>
<!-- Date -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Date :"
android:textSize="14sp"
android:textColor="@color/Grey"/>
<TextView
android:id="@+id/details_date_value"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="11 Apr 2024"
android:textSize="14sp"
android:textColor="@android:color/black"/>
</LinearLayout>
<!-- Time Slot -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Time Slot :"
android:textSize="14sp"
android:textColor="@color/Grey"/>
<TextView
android:id="@+id/details_time_value"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="10:00 AM"
android:textSize="14sp"
android:textColor="@android:color/black"/>
</LinearLayout>
<!-- Location -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Location :"
android:textSize="14sp"
android:textColor="@color/Grey"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/details_location_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A2-1-2, Block A, Ashlar Residence, 63105, Selangor"
android:textSize="14sp"
android:textColor="@android:color/black"/>
<TextView
android:id="@+id/locate_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Locate"
android:textSize="14sp"
android:textColor="@color/colorPrimary"
android:textStyle="bold"
android:layout_marginTop="4dp"
android:clickable="true"
android:focusable="true"/>
</LinearLayout>
</LinearLayout>
<!-- Terms & Conditions -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Terms &amp;\nConditions :"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginEnd="16dp"/>
<TextView
android:id="@+id/view_terms_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="View here"
android:textSize="14sp"
android:textColor="@color/colorPrimary"
android:textStyle="bold"
android:clickable="true"
android:focusable="true"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Add to Calendar Button -->
<Button
android:id="@+id/add_to_calendar_button"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="Add to Calendar"
android:textColor="@android:color/black"
android:textSize="16sp"
android:drawableLeft="@android:drawable/ic_menu_my_calendar"
android:drawableTint="@android:color/black"
android:backgroundTint="@android:color/white"
app:strokeColor="@color/Grey"
app:strokeWidth="1dp"
app:cornerRadius="12dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_marginBottom="16dp"/>
</LinearLayout>
<!-- Owner Info Content (Initially Hidden) -->
<LinearLayout
android:id="@+id/owner_info_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<!-- Primary Owner Section -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Primary Owner"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="16dp"/>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeWidth="1dp"
app:strokeColor="#E0E0E0"
android:layout_marginBottom="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<!-- Name -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="140dp"
android:layout_height="wrap_content"
android:text="Name :"
android:textSize="14sp"
android:textColor="@color/Grey"/>
<TextView
android:id="@+id/details_owner_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="John Anthony Snow"
android:textSize="14sp"
android:textColor="@android:color/black"/>
</LinearLayout>
<!-- NRIC / Passport No. -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="140dp"
android:layout_height="wrap_content"
android:text="NRIC /\nPassport No. :"
android:textSize="14sp"
android:textColor="@color/Grey"/>
<TextView
android:id="@+id/details_owner_nric"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="951109057718"
android:textSize="14sp"
android:textColor="@android:color/black"/>
</LinearLayout>
<!-- Contact No. -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="140dp"
android:layout_height="wrap_content"
android:text="Contact No. :"
android:textSize="14sp"
android:textColor="@color/Grey"/>
<TextView
android:id="@+id/details_owner_contact"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="+60178006540"
android:textSize="14sp"
android:textColor="@color/colorPrimary"
android:textStyle="bold"
android:clickable="true"
android:focusable="true"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</LinearLayout>
</ScrollView>
<!-- Bottom Buttons -->
<LinearLayout
android:id="@+id/bottom_buttons_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp"
android:background="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent">
<!-- Cancel Appointment Button -->
<Button
android:id="@+id/cancel_appointment_button"
android:layout_width="match_parent"
android:layout_height="64dp"
android:text="Cancel Appointment"
android:textSize="16sp"
android:textColor="@android:color/white"
android:backgroundTint="#FF6B6B"
app:cornerRadius="32dp"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F5F5F5">
<!-- Filter Dropdowns -->
<LinearLayout
android:id="@+id/filter_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:background="@android:color/white"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/type_filter_layout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:hint="Filter Type">
<AutoCompleteTextView
android:id="@+id/type_filter_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:text="All Type"
android:textSize="14sp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/status_filter_layout"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:hint="Filter Status">
<AutoCompleteTextView
android:id="@+id/status_filter_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:text="Upcoming"
android:textSize="14sp"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<!-- Search Bar -->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/search_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:startIconDrawable="@android:drawable/ic_menu_search"
app:boxBackgroundColor="@android:color/white"
app:layout_constraintTop_toBottomOf="@id/filter_container">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/search_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Search Unit No. or Owner Name..."
android:textSize="14sp"/>
</com.google.android.material.textfield.TextInputLayout>
<!-- SwipeRefreshLayout for Pull-to-Refresh -->
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/search_layout"
app:layout_constraintBottom_toBottomOf="parent">
<!-- RecyclerView for Appointments List -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/appointments_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="80dp"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<!-- Empty State -->
<LinearLayout
android:id="@+id/empty_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No Appointments"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/darker_gray"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="You haven't made any appointments yet"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginTop="8dp"/>
</LinearLayout>
<!-- Floating Action Button to Add New Appointment -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_add_appointment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:src="@android:drawable/ic_input_add"
app:tint="@android:color/white"
app:backgroundTint="@color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="24dp"
android:background="@android:color/white">
<!-- Title -->
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Appointment Type"
android:textSize="24sp"
android:textColor="@color/black"
android:textStyle="bold"
android:layout_marginBottom="8dp" />
<!-- Subtitle -->
<TextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Choose the type of appointment you want to make"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginBottom="32dp" />
<!-- ScrollView for appointment type options -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Handover Card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_handover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeColor="@color/colorPrimary"
app:strokeWidth="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Handover"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Schedule a handover appointment for your unit"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginTop="4dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Rectification Card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_rectification"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeColor="@android:color/transparent"
app:strokeWidth="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rectification"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Schedule a rectification appointment for defect repairs"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginTop="4dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Joint Inspection Card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_joint_inspection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeColor="@android:color/transparent"
app:strokeWidth="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Joint Inspection"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Schedule a joint inspection with the developer"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginTop="4dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Viewing Card -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_viewing"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="12dp"
app:cardElevation="2dp"
app:strokeColor="@android:color/transparent"
app:strokeWidth="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Viewing"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Schedule a viewing appointment for your unit"
android:textSize="14sp"
android:textColor="@color/Grey"
android:layout_marginTop="4dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>
<!-- Next Button -->
<Button
android:id="@+id/next_button"
android:layout_width="match_parent"
android:layout_height="56dp"
android:text="Next"
android:textSize="16sp"
android:textColor="@android:color/white"
android:backgroundTint="@color/Grey"
android:enabled="false"
android:layout_marginTop="16dp" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
app:strokeWidth="1dp"
app:strokeColor="#E0E0E0">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- Header: Type Badge and Time -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<!-- Type Badge -->
<TextView
android:id="@+id/appointment_type_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Handover"
android:textColor="@android:color/white"
android:textSize="12sp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:background="@drawable/badge_handover"
android:layout_marginEnd="8dp"/>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"/>
<!-- Time -->
<TextView
android:id="@+id/appointment_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="09:00 AM"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"/>
</LinearLayout>
<!-- Unit Number -->
<TextView
android:id="@+id/appointment_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A-3-11"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginTop="8dp"/>
<!-- Location -->
<TextView
android:id="@+id/appointment_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="John Anthony Snow"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginTop="4dp"/>
<!-- Status Badge -->
<TextView
android:id="@+id/appointment_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Confirmed"
android:textColor="@android:color/white"
android:textSize="12sp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:background="@drawable/badge_confirmed"
android:layout_marginTop="8dp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#F5F5F5">
<!-- Date Header (only shown for first item of each date) -->
<TextView
android:id="@+id/date_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:paddingBottom="8dp"
android:text="Thu, 11 Apr 2025"
android:textSize="14sp"
android:textColor="#666666"
android:visibility="gone"/>
<!-- Appointment Card -->
<androidx.cardview.widget.CardView
android:id="@+id/appointment_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
app:cardBackgroundColor="@android:color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<!-- Left Section: Time and Badge -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginEnd="24dp">
<!-- Time -->
<TextView
android:id="@+id/appointment_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="02:30 PM"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_marginBottom="8dp"/>
<!-- Type Badge -->
<TextView
android:id="@+id/appointment_type_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/badge_handover"
android:paddingHorizontal="10dp"
android:paddingVertical="3dp"
android:text="Handover"
android:textColor="@android:color/white"
android:textSize="13sp" />
</LinearLayout>
<!-- Right Section -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<!-- Unit Number -->
<TextView
android:id="@+id/appointment_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A-3-11"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_marginBottom="4dp"/>
<!-- Type Badge and Location (on same line) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:baselineAligned="false">
<TextView
android:id="@+id/appointment_location"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="John Anthony Snow"
android:textSize="14sp"
android:textColor="#666666"
android:maxLines="1"
android:ellipsize="end"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment