This commit is contained in:
InsaneTrashRU 2025-06-06 16:23:30 +03:00
commit 0d298ff597
405 changed files with 34720 additions and 0 deletions

15
.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

3
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

1
.idea/.name generated Normal file
View File

@ -0,0 +1 @@
Rehabilitation

123
.idea/codeStyles/Project.xml generated Normal file
View File

@ -0,0 +1,123 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

6
.idea/compiler.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" />
</component>
</project>

17
.idea/deploymentTargetDropDown.xml generated Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="C:\Users\maksi\.android\avd\Pixel_6_API_29.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-11-28T12:28:18.723737700Z" />
</component>
</project>

10
.idea/deploymentTargetSelector.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

20
.idea/gradle.xml generated Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$PROJECT_DIR$/../../../../Gradle/gradle-8.2" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

6
.idea/kotlinc.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.8.0" />
</component>
</project>

10
.idea/migrations.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

16
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,16 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
<component name="VisualizationToolProject">
<option name="state">
<ProjectState>
<option name="scale" value="0.33" />
</ProjectState>
</option>
</component>
</project>

714
.idea/other.xml generated Normal file
View File

@ -0,0 +1,714 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="direct_access_persist.xml">
<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="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="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="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="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="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="manufacturer" value="SHARP" />
<option name="name" value="AQUOS sense2 SH-01L" />
<option name="screenDensity" value="480" />
<option name="screenX" value="1080" />
<option name="screenY" value="2160" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="a15" />
<option name="id" value="a15" />
<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="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="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="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="31" />
<option name="brand" value="samsung" />
<option name="codename" value="a51" />
<option name="id" value="a51" />
<option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy A51" />
<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="akita" />
<option name="id" value="akita" />
<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="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="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="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="manufacturer" value="Samsung" />
<option name="name" value="Flip 6" />
<option name="screenDensity" value="340" />
<option name="screenX" value="1080" />
<option name="screenY" value="2640" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="32" />
<option name="brand" value="google" />
<option name="codename" value="bluejay" />
<option name="id" value="bluejay" />
<option name="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="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="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="id" value="comet" />
<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="id" value="comet" />
<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="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="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="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="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="id" value="e1q" />
<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="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="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="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="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="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="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="manufacturer" value="Motorola" />
<option name="name" value="moto g34 5G" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="g0q" />
<option name="id" value="g0q" />
<option name="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="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="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="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="id" value="gts8uwifi" />
<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="id" value="gts8wifi" />
<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="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="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="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="manufacturer" value="Motorola" />
<option name="name" value="G20" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="komodo" />
<option name="id" value="komodo" />
<option name="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="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="33" />
<option name="brand" value="google" />
<option name="codename" value="lynx" />
<option name="id" value="lynx" />
<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="manaus" />
<option name="id" value="manaus" />
<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="manufacturer" value="Motorola" />
<option name="name" value="moto g play - 2023" />
<option name="screenDensity" value="280" />
<option name="screenX" value="720" />
<option name="screenY" value="1600" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="samsung" />
<option name="codename" value="o1q" />
<option name="id" value="o1q" />
<option name="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="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="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="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="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="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="id" value="r11" />
<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="manufacturer" value="Samsung" />
<option name="name" value="SM-S711U" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2340" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="30" />
<option name="brand" value="google" />
<option name="codename" value="redfin" />
<option name="id" value="redfin" />
<option name="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="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="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="id" value="tangorpro" />
<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="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="id" value="tokay" />
<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="id" value="tokay" />
<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="manufacturer" value="Samsung" />
<option name="name" value="SM-G556B" />
<option name="screenDensity" value="450" />
<option name="screenX" value="1080" />
<option name="screenY" value="2408" />
</PersistentDeviceSelectionData>
</list>
</option>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

1
app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

83
app/build.gradle Normal file
View File

@ -0,0 +1,83 @@
plugins {
id 'kotlin-kapt'
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.google.gms.google-services'
}
android {
namespace 'com.example.rehabilitation'
compileSdk 33
defaultConfig {
applicationId "com.example.rehabilitation"
minSdk 28
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures{
viewBinding true
}
}
dependencies {
implementation 'androidx.room:room-ktx:2.5.2'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1'
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1"
implementation 'androidx.fragment:fragment-ktx:1.5.5'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.1.17'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.android.car.ui:car-ui-lib:2.0.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'org.apache.poi:poi:5.2.3'
implementation group: 'org.apache.poi', name: 'poi-ooxml', version: '5.2.3'
implementation group: 'org.apache.poi', name: 'poi', version: '5.2.3'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
implementation 'com.kizitonwose.calendar:view:2.0.0'
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1"
//Retrofit
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
//OkHttp
implementation "com.squareup.okhttp3:logging-interceptor:4.7.2"
implementation "com.squareup.okhttp3:okhttp:4.7.2"
implementation 'com.squareup.picasso:picasso:2.71828'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
implementation 'com.kizitonwose.calendar:view:2.0.0'
}

69
app/google-services.json Normal file
View File

@ -0,0 +1,69 @@
{
"project_info": {
"project_number": "1027818028999",
"firebase_url": "https://rehabilitationtest-default-rtdb.europe-west1.firebasedatabase.app",
"project_id": "rehabilitationtest",
"storage_bucket": "rehabilitationtest.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:1027818028999:android:a97724d7840d06fdada3e2",
"android_client_info": {
"package_name": "com.example.rehabilitation"
}
},
"oauth_client": [
{
"client_id": "1027818028999-a75qvvvqqb81ber25k6eeq1fqpr60oam.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAHvjzE2QIaIrCD9NOD1f_rShI4eXPyFVo"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "1027818028999-a75qvvvqqb81ber25k6eeq1fqpr60oam.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:1027818028999:android:1459bab345b4bf66ada3e2",
"android_client_info": {
"package_name": "com.example.user"
}
},
"oauth_client": [
{
"client_id": "1027818028999-a75qvvvqqb81ber25k6eeq1fqpr60oam.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAHvjzE2QIaIrCD9NOD1f_rShI4eXPyFVo"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "1027818028999-a75qvvvqqb81ber25k6eeq1fqpr60oam.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}

21
app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,24 @@
package com.example.rehabilitation
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.rehabilitation", appContext.packageName)
}
}

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher_logov2"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_logov2"
android:supportsRtl="true"
android:theme="@style/Theme.Rehabilitation"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
<activity
android:name=".Auth.AuthorizationActivity"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:screenOrientation="portrait"
android:value="" />
</activity>
<activity
android:name=".CodeError.Code429Activity"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:screenOrientation="portrait"
android:value="" />
</activity>
<activity
android:name=".CodeError.Code500Activity"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:screenOrientation="portrait"
android:value="" />
</activity>
<activity
android:name=".MainActivity"
android:exported="true"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan|stateAlwaysHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Enternet.EnternetActivity"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:screenOrientation="portrait"
android:value="" />
</activity>
</application>
</manifest>

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

View File

@ -0,0 +1,177 @@
package com.example.admin
import android.app.Activity
import android.graphics.Color
import android.view.Gravity
import android.view.LayoutInflater
import android.widget.TextView
import android.widget.Toast
import com.example.rehabilitation.R
import com.example.rehabilitation.databinding.CustomToastBinding
/**
* Расширение для класса Toast, добавляющее возможность отображения пользовательских уведомлений
* с кастомным дизайном и анимацией
*/
fun Toast.showCustomInfoToast(message: String, activity: Activity) {
// Создание кастомного layout для Toast
val layout = LayoutInflater.from(activity).inflate(R.layout.custom_toast, null)
// Настройка текста сообщения
val text = layout.findViewById<TextView>(R.id.text)
text.text = message
// Настройка параметров Toast
this.apply {
setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, 100)
duration = Toast.LENGTH_LONG
view = layout
}
// Отображение Toast
show()
}
/**
* Расширение для класса Toast, добавляющее возможность отображения уведомлений об ошибках
* с красным фоном
*/
fun Toast.showErrorToast(message: String, activity: Activity) {
// Создание кастомного layout для Toast
val layout = LayoutInflater.from(activity).inflate(R.layout.custom_toast, null)
// Настройка текста сообщения
val text = layout.findViewById<TextView>(R.id.text)
text.text = message
text.setTextColor(Color.WHITE)
// Установка красного фона
layout.setBackgroundColor(Color.RED)
// Настройка параметров Toast
this.apply {
setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, 100)
duration = Toast.LENGTH_LONG
view = layout
}
// Отображение Toast
show()
}
/**
* Расширение для класса Toast, добавляющее возможность отображения уведомлений об успехе
* с зеленым фоном
*/
fun Toast.showSuccessToast(message: String, activity: Activity) {
// Создание кастомного layout для Toast
val layout = LayoutInflater.from(activity).inflate(R.layout.custom_toast, null)
// Настройка текста сообщения
val text = layout.findViewById<TextView>(R.id.text)
text.text = message
text.setTextColor(Color.WHITE)
// Установка зеленого фона
layout.setBackgroundColor(Color.GREEN)
// Настройка параметров Toast
this.apply {
setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, 100)
duration = Toast.LENGTH_LONG
view = layout
}
// Отображение Toast
show()
}
/**
* Объект для отображения кастомных уведомлений
* Расширяет стандартный Toast для отображения уведомлений с анимацией
*/
object Toast {
/**
* Отображение информационного уведомления
* @param context Контекст приложения
* @param message Текст уведомления
*/
fun showCustomInfoToast(context: Context, message: String) {
// Создание и настройка уведомления
val toast = Toast(context)
val binding = CustomToastBinding.inflate(context.layoutInflater)
// Настройка внешнего вида
binding.root.setBackgroundResource(R.drawable.bg_info_toast)
binding.ivIcon.setImageResource(R.drawable.ic_info)
binding.tvMessage.text = message
// Настройка параметров отображения
toast.setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, 100)
toast.duration = Toast.LENGTH_LONG
toast.view = binding.root
// Добавление анимации
toast.view?.alpha = 0f
toast.view?.animate()?.alpha(1f)?.setDuration(300)?.start()
// Отображение уведомления
toast.show()
}
/**
* Отображение уведомления об ошибке
* @param context Контекст приложения
* @param message Текст уведомления
*/
fun showErrorToast(context: Context, message: String) {
// Создание и настройка уведомления
val toast = Toast(context)
val binding = CustomToastBinding.inflate(context.layoutInflater)
// Настройка внешнего вида
binding.root.setBackgroundResource(R.drawable.bg_error_toast)
binding.ivIcon.setImageResource(R.drawable.ic_error)
binding.tvMessage.text = message
// Настройка параметров отображения
toast.setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, 100)
toast.duration = Toast.LENGTH_LONG
toast.view = binding.root
// Добавление анимации
toast.view?.alpha = 0f
toast.view?.animate()?.alpha(1f)?.setDuration(300)?.start()
// Отображение уведомления
toast.show()
}
/**
* Отображение уведомления об успешном выполнении
* @param context Контекст приложения
* @param message Текст уведомления
*/
fun showSuccessToast(context: Context, message: String) {
// Создание и настройка уведомления
val toast = Toast(context)
val binding = CustomToastBinding.inflate(context.layoutInflater)
// Настройка внешнего вида
binding.root.setBackgroundResource(R.drawable.bg_success_toast)
binding.ivIcon.setImageResource(R.drawable.ic_success)
binding.tvMessage.text = message
// Настройка параметров отображения
toast.setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, 100)
toast.duration = Toast.LENGTH_LONG
toast.view = binding.root
// Добавление анимации
toast.view?.alpha = 0f
toast.view?.animate()?.alpha(1f)?.setDuration(300)?.start()
// Отображение уведомления
toast.show()
}
}

View File

@ -0,0 +1,17 @@
package com.example.rehabilitation.Adapter
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
class VpAdapter(fr_act:FragmentActivity, private val list:List<Fragment>):FragmentStateAdapter(fr_act) {//private val list:List<Fragment> - список с фрагментами сюда передастся, тоесть с двумя фрагментами
//Возврощаем для createFragment количество элементов(фрагментов) в листе(List)
override fun getItemCount(): Int {
return list.size//возврощаем количество фрагметов
}
//Позиция фрагмента или 1 или 2, то есть 0 или 1. И по позиции будут выводится фрагмент.
override fun createFragment(position: Int): Fragment {
return list[position]//Возврощаем фрагмент из листа по позиции
}
}

View File

@ -0,0 +1,245 @@
package com.example.rehabilitation.Appeals
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.activityViewModels
import com.example.rehabilitation.Adapter.VpAdapter
import com.example.rehabilitation.Appeals.TabLayout.NewAppealsFragment
import com.example.rehabilitation.Appeals.TabLayout.OldAppealsFragment
import com.example.rehabilitation.Auth.AuthorizationActivity
import com.example.rehabilitation.CodeError.Code429Activity
import com.example.rehabilitation.CodeError.Code500Activity
import com.example.rehabilitation.Enternet.EnternetActivity
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.PatientViewModel
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.R
import com.example.rehabilitation.Retrofit.PatientApi
import com.example.rehabilitation.databinding.FragmentAppealsBinding
import com.google.android.material.tabs.TabLayoutMediator
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.Timer
import kotlin.concurrent.fixedRateTimer
class AppealsFragment : Fragment() {
private lateinit var binding: FragmentAppealsBinding
private val modelPatient: PatientViewModel by activityViewModels()
private lateinit var patientApi: PatientApi
private lateinit var timer: Timer
val prefPatientConclusion = ConclusionPref()
//Класс проверки интеренета
val enternetCheck = EnternetCheck()
private val tList = listOf(
"новые",
"обработанные",
)
//Список с фрагментами для переключения
private val flist = listOf(
NewAppealsFragment.newInstance(),
OldAppealsFragment.newInstance(),
)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentAppealsBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
init()
binding.btnAddMessage.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.CLAppeals, CreateMessageFragment.newInstance())?.commit()
binding.ConstrainLayoutProductEdit.visibility = View.GONE
binding.CLAppeals.visibility = View.VISIBLE
}
// fixedRateTimer("timer", false, 0, 10000) {
// activity?.runOnUiThread {
//
// }
// }
}
private fun getOldAppeals() {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val listAppeals = patientApi.GetAppealsPatientOld("Bearer $Tokens")
requireActivity().runOnUiThread {
//Фиксируем полученные данные
val List = listAppeals.body()
val Nice = listAppeals.isSuccessful
val Code = listAppeals.code()
if(Code==429){
val intetn = Intent(requireContext(), Code429Activity::class.java)
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
if(List.appeals_old != null){
modelPatient.appealsOldList.value = List.appeals_old
}
}
}
getNewAppeals()
}
else if (Code == 500) {
val intetn = Intent(requireContext(), Code500Activity::class.java)
startActivity(intetn)
}
else if (Code == 401) {
val intetn = Intent(requireContext(), AuthorizationActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
}
}
//Получение необработанных сообщений
private fun getNewAppeals() {
if (enternetCheck.isOnline(requireContext())) {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val listAppeals = patientApi.GetAppealsPatientNew("Bearer $Tokens")
requireActivity().runOnUiThread {
//Фиксируем полученные данные
val List = listAppeals.body()
val Nice = listAppeals.isSuccessful
val Code = listAppeals.code()
if(Code==429){
val intetn = Intent(requireContext(), Code429Activity::class.java)
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
if(List.appeals_new != null){
modelPatient.appealsNewList.value = List.appeals_new
}
}
}
}
else if (Code == 500) {
val intetn = Intent(requireContext(), Code500Activity::class.java)
startActivity(intetn)
}
else if (Code == 401) {
val intetn = Intent(requireContext(), AuthorizationActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
}
} else {
val intetn = Intent(requireContext(), EnternetActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
//Инициализируем Retrofit
private fun initRetrofit() {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient
.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("http://mobileapp.vmeda.org/api/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
patientApi = retrofit.create(PatientApi::class.java)
}
//Функция подключения переключения
private fun init() = with(binding) {
val adapter = VpAdapter(activity as FragmentActivity, flist)
vpProduct.adapter = adapter
//Переключения (связываем таблаяут(переключатель) с viewpager, чтобы переключать фрагменты)
TabLayoutMediator(tabLayoutProduct, vpProduct) { tab, pos ->
tab.text =
tList[pos]//tab - нажатая кнопка, pos - позиция кнопки, tList[pos] - передаем название по полученной позиции
}.attach()// attach() - чтобы все переключалось, а не вывадило постоянно один экран
//Изменения цвета в зависомости на каком из tabLayout вы находитесь
binding.tabLayoutProduct.setTabTextColors(getResources().getColor(R.color.black),
getResources().getColor(R.color.white));
}
companion object {
fun newInstance() = AppealsFragment()
}
override fun onResume() {
super.onResume()
checkForUpdates(true)
}
override fun onStop() {
super.onStop()
timer.cancel()
timer.purge()
}
private fun checkForUpdates(daemonIsTrue: Boolean) {
timer = fixedRateTimer("default", daemonIsTrue, 0, 15000) {
activity?.runOnUiThread {
getOldAppeals()
}
}
}
}

View File

@ -0,0 +1,118 @@
package com.example.rehabilitation.Appeals
import android.annotation.SuppressLint
import android.os.Handler
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.rehabilitation.Appeals.TabLayout.Model.AppealsNewModel
import com.example.rehabilitation.R
import com.example.rehabilitation.databinding.ItemAppealsNewBinding
class AppealsNewAdapter(val listener_check_apeals: Listener, val listener_patient_apeals: Listener2) :
ListAdapter<AppealsNewModel, AppealsNewAdapter.Holder>(
Comparator()
) {//Productitem - по этой форме будем заполнять.//ProductAdapter.holder - это создаваемый holder который хранит логику как нужно заполнять карточку
//В holder создаетс код с помошью которого мы будем заполнять и сохронять разметку
class Holder(view: View, val listener_check_apeals: Listener, val listener_patient_apeals: Listener2) :
RecyclerView.ViewHolder(view) {//Класс который будет хранить сссылки на элементы, и отвечает за один элемент за 1 раз, то есть сначсало нулевой элемент заполнит, потом первый, потом второй и т.д.
//Для передачи данных
val binding =
ItemAppealsNewBinding.bind(view)//view - здесь храянтся элементы и мы их bind заполним в ListItemBinding//ListItemBinding - это клласс даннйо разметки(карточки) которую мы будем заполнять, а нужна дання переменная(binding), чтобы мжно было при заполнение обращатся к элементам карточки
var itemTemp: AppealsNewModel? =
null//Глобальная переменная для нашего item, чтобы можно было передать данные для нажатия
//init - дает возможность внутри адаптера обращаться к элементам экрана
init {
binding.btnAdd.setOnClickListener {//Нажатие на ячейку//itemView - это весь элемент карточки из списка
//itemView.setEnabled(false)
itemTemp?.let { it1 -> listener_check_apeals.onClickAppeals(it1) }
}
binding.btnPatient.setOnClickListener {//Нажатие на ячейку//itemView - это весь элемент карточки из списка
//itemView.setEnabled(false)
itemTemp?.let { it2 -> listener_check_apeals.onClickAppeals(it2) }
}
}
@SuppressLint("SuspiciousIndentation")
fun bind(item: AppealsNewModel) = with(binding) {//Productitem - перпедаем данные
itemTemp = item
txtNumber.text = item.number.toString()+"."
txtAppeals.text = item.text
txtLoginPatient.text = item.login
if (item.expand) {
txtAppeals.maxLines = 30
} else {
txtAppeals.maxLines = 1
}
CardViewNew.setOnClickListener {
if (item.expand == false) {
txtAppeals.maxLines = 100
item.expand = true
} else {
txtAppeals.maxLines = 1
item.expand = false
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_appeals_new, parent, false)//Создаем(надуваем) list_item
return Holder(view, listener_check_apeals,listener_patient_apeals)//Через Holder возврощаем view
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val view = holder.bind(getItem(position))//Заполняем по позиции карточку
}
//Comparator - сравнивает старый список и новый и если что-то изменилось, то работает с конкретным изменением списке, а не весь список переписывает
class Comparator : DiffUtil.ItemCallback<AppealsNewModel>() {
override fun areItemsTheSame(
oldItem: AppealsNewModel,
newItem: AppealsNewModel
): Boolean {//Тут лучше всего сравнивать по id//oldItem - элементы старого списка, newItem - элементы нового списка//Возврощает Boolean, тоесть есть изменения или нет
return oldItem.id == newItem.id//Сравниваем полностью весь список новы и старый, по очередно по одной карточке и по элементно, то есть нулевой элемент, первый, второй и т.д.. Но лучше сравнивать по id списки, а не просто весь список, так как это эфективнее, так как id уникальный(oldItem.id == newItem.id)
}
override fun areContentsTheSame(
oldItem: AppealsNewModel,
newItem: AppealsNewModel
): Boolean {//Утут нужно сравнивать весь спсок старых элементов и новых
return oldItem == newItem//Сравниваем полностью весь список новы и старый
}
}
interface Listener {
fun onClickAppeals(item: AppealsNewModel)
}
interface Listener2 {
fun onClickAppealsPatient(item: AppealsNewModel)
}
}

View File

@ -0,0 +1,110 @@
package com.example.rehabilitation.Appeals
import android.annotation.SuppressLint
import android.opengl.Visibility
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.rehabilitation.Appeals.TabLayout.Model.AppealsOldModel
import com.example.rehabilitation.R
import com.example.rehabilitation.databinding.ItemAppealsOldBinding
class AppealsOldAdapter(val listener_zakaz: Listener) :
ListAdapter<AppealsOldModel, AppealsOldAdapter.Holder>(
Comparator()
) {//Productitem - по этой форме будем заполнять.//ProductAdapter.holder - это создаваемый holder который хранит логику как нужно заполнять карточку
//В holder создаетс код с помошью которого мы будем заполнять и сохронять разметку
class Holder(view: View, val listener_zakaz: Listener) :
RecyclerView.ViewHolder(view) {//Класс который будет хранить сссылки на элементы, и отвечает за один элемент за 1 раз, то есть сначсало нулевой элемент заполнит, потом первый, потом второй и т.д.
//Для передачи данных
val binding =
ItemAppealsOldBinding.bind(view)//view - здесь храянтся элементы и мы их bind заполним в ListItemBinding//ListItemBinding - это клласс даннйо разметки(карточки) которую мы будем заполнять, а нужна дання переменная(binding), чтобы мжно было при заполнение обращатся к элементам карточки
var itemTemp: AppealsOldModel? =
null//Глобальная переменная для нашего item, чтобы можно было передать данные для нажатия
//init - дает возможность внутри адаптера обращаться к элементам экрана
init {
itemView.setOnClickListener {//Нажатие на ячейку//itemView - это весь элемент карточки из списка
itemView.setEnabled(false)
itemTemp?.let { it1 -> listener_zakaz.onClickAppeals(it1) }
}
}
@SuppressLint("SuspiciousIndentation")
fun bind(item: AppealsOldModel) = with(binding) {//Productitem - перпедаем данные
itemTemp = item
txtNumber.text = item.number.toString()+"."
txtAppeals.text = item.text
txtLoginPatient.text = item.login
if (item.expand) {
binding.txtAppeals.maxLines = 100
} else {
binding.txtAppeals.maxLines = 1
}
binding.CardViewOld.setOnClickListener {
if (item.expand == false) {
binding.txtAppeals.maxLines = 100
item.expand = true
} else {
binding.txtAppeals.maxLines = 1
item.expand = false
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_appeals_old, parent, false)//Создаем(надуваем) list_item
return Holder(view, listener_zakaz)//Через Holder возврощаем view
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val view = holder.bind(getItem(position))//Заполняем по позиции карточку
}
//Comparator - сравнивает старый список и новый и если что-то изменилось, то работает с конкретным изменением списке, а не весь список переписывает
class Comparator : DiffUtil.ItemCallback<AppealsOldModel>() {
override fun areItemsTheSame(
oldItem: AppealsOldModel,
newItem: AppealsOldModel
): Boolean {//Тут лучше всего сравнивать по id//oldItem - элементы старого списка, newItem - элементы нового списка//Возврощает Boolean, тоесть есть изменения или нет
return oldItem.id == newItem.id//Сравниваем полностью весь список новы и старый, по очередно по одной карточке и по элементно, то есть нулевой элемент, первый, второй и т.д.. Но лучше сравнивать по id списки, а не просто весь список, так как это эфективнее, так как id уникальный(oldItem.id == newItem.id)
}
override fun areContentsTheSame(
oldItem: AppealsOldModel,
newItem: AppealsOldModel
): Boolean {//Утут нужно сравнивать весь спсок старых элементов и новых
return oldItem == newItem//Сравниваем полностью весь список новы и старый
}
}
//Интерфейс нажатия на кнопку удалить товар из корзины
interface Listener {
fun onClickAppeals(item: AppealsOldModel)
}
}

View File

@ -0,0 +1,153 @@
package com.example.rehabilitation.Appeals
import android.content.Intent
import android.os.Bundle
import android.transition.TransitionInflater
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.activityViewModels
import com.example.admin.Toast.showCustomInfoToast
import com.example.rehabilitation.Auth.AuthorizationActivity
import com.example.rehabilitation.CodeError.Code429Activity
import com.example.rehabilitation.CodeError.Code500Activity
import com.example.rehabilitation.Enternet.EnternetActivity
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.Pref.ClearPref
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.R
import com.example.rehabilitation.Retrofit.PatientApi
import com.example.rehabilitation.databinding.FragmentCreateMessageBinding
import com.example.rehabilitation.model_adapter.DataModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class CreateMessageFragment : Fragment() {
private lateinit var binding: FragmentCreateMessageBinding
private val dataModel: DataModel by activityViewModels()//Для передачи данных
private lateinit var patientApi: PatientApi
val prefDoctorConclusion = ConclusionPref()
val prefDoctorClear = ClearPref()
//Класс проверки интеренета
val enternetCheck = EnternetCheck()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentCreateMessageBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val inflater = TransitionInflater.from(requireContext())
enterTransition = inflater.inflateTransition(R.transition.slide_right)
exitTransition = inflater.inflateTransition(R.transition.slide_right)
binding.btnAddMessagePatient.setOnClickListener{
val text = binding.edTextMessagePatient.text.toString()
if(text!=""){
AddMessageDoctor()
}
else{
Toast(requireContext()).showCustomInfoToast("Поле пустое", requireActivity())
}
}
binding.btnExit.setOnClickListener{
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.placeHolderFragment, AppealsFragment.newInstance())
//?.addToBackStack(null)
?.commit()
}
}
//Отправка сообщения
fun AddMessageDoctor() {
if (enternetCheck.isOnline(requireContext())) {
initRetrofit()
val Tokens = prefDoctorConclusion.conclusionToken(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val message = patientApi.AddMessagePatient("Bearer $Tokens",binding.edTextMessagePatient.text.toString())
requireActivity().runOnUiThread {
//Фиксируем полученные данные
val List = message.body()
val Nice = message.isSuccessful
val Code = message.code()
if(Code==429){
val intetn = Intent(requireContext(), Code429Activity::class.java)
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
Toast(requireContext()).showCustomInfoToast(List.message, requireActivity())
}
}
}
else if (Code == 500) {
val intetn = Intent(requireContext(), Code500Activity::class.java)
startActivity(intetn)
}
else if (Code == 401) {
val intetn = Intent(requireContext(), AuthorizationActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
}
} else {
val intetn = Intent(requireContext(), EnternetActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
//Инициализируем Retrofit
private fun initRetrofit() {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient
.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://rehabilitation.vmeda.org/api/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
patientApi = retrofit.create(PatientApi::class.java)
}
companion object {
fun newInstance() = CreateMessageFragment()
}
}

View File

@ -0,0 +1,6 @@
package com.example.rehabilitation.Appeals.TabLayout.Model
data class AppealsNewListModel(
val appeals_new: List<AppealsNewModel>
)

View File

@ -0,0 +1,16 @@
package com.example.rehabilitation.Appeals.TabLayout.Model
data class AppealsNewModel(
val id: Int,
val number: Int,
val text: String,
val id_patient: Int,
val id_doctor: Int,
val check: Int,
val login: String,
val created_at: String,
val updated_at: String,
var expand : Boolean = false,
)

View File

@ -0,0 +1,6 @@
package com.example.rehabilitation.Appeals.TabLayout.Model
data class AppealsOldListModel(
val appeals_old: List<AppealsOldModel>
)

View File

@ -0,0 +1,16 @@
package com.example.rehabilitation.Appeals.TabLayout.Model
data class AppealsOldModel(
val id: Int,
val number: Int,
val text: String,
val id_patient: Int,
val id_doctor: Int,
val check: Int,
val login: String,
val created_at: String,
val updated_at: String,
var expand : Boolean = false,
)

View File

@ -0,0 +1,284 @@
package com.example.rehabilitation.Appeals.TabLayout
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.GridLayoutManager
import com.example.admin.Toast.showCustomInfoToast
import com.example.rehabilitation.Appeals.AppealsNewAdapter
import com.example.rehabilitation.Appeals.TabLayout.Model.AppealsNewModel
import com.example.rehabilitation.Auth.AuthorizationActivity
import com.example.rehabilitation.CodeError.Code429Activity
import com.example.rehabilitation.CodeError.Code500Activity
import com.example.rehabilitation.Enternet.EnternetActivity
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.PatientViewModel
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.Retrofit.PatientApi
import com.example.rehabilitation.databinding.FragmentNewAppealsBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class NewAppealsFragment : Fragment(), AppealsNewAdapter.Listener, AppealsNewAdapter.Listener2 {
private lateinit var binding: FragmentNewAppealsBinding
private val modelPatient: PatientViewModel by activityViewModels()
lateinit var adapter: AppealsNewAdapter
private lateinit var patientApi: PatientApi
val prefPatientConclusion = ConclusionPref()
//Список обрашений новых
var appealsNewList: List<AppealsNewModel>? = null
//Класс проверки интеренета
val enternetCheck = EnternetCheck()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentNewAppealsBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initRcViewAppeals()
patientListCurrent()
modelPatient.appealsNewList.observe(viewLifecycleOwner) {//viewLifecycleOwner - следит за циклом жизни fragment
if(appealsNewList != it){
appealsNewList = it
adapter.submitList(it)//Напрямую переадем созданный список в adapter(ProductAdapter)
}
}
getNewAppeals()
}
//Получение необработанных сообщений
private fun getNewAppeals() {
if (enternetCheck.isOnline(requireContext())) {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val listAppeals = patientApi.GetAppealsPatientNew("Bearer $Tokens")
requireActivity().runOnUiThread {
//Фиксируем полученные данные
val List = listAppeals.body()
val Nice = listAppeals.isSuccessful
val Code = listAppeals.code()
if(Code==429){
val intetn = Intent(requireContext(), Code429Activity::class.java)
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
if(List.appeals_new != null){
binding.txtNull.visibility = View.GONE
modelPatient.appealsNewList.value = List.appeals_new
}
else{
binding.txtNull.visibility = View.VISIBLE
}
}
else{
binding.txtNull.visibility = View.VISIBLE
}
}
}
else if (Code == 500) {
val intetn = Intent(requireContext(), Code500Activity::class.java)
startActivity(intetn)
}
else if (Code == 401) {
val intetn = Intent(requireContext(), AuthorizationActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
}
} else {
val intetn = Intent(requireContext(), EnternetActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
private fun getOldAppeals() {
if (enternetCheck.isOnline(requireContext())) {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val listAppeals = patientApi.GetAppealsPatientOld("Bearer $Tokens")
requireActivity().runOnUiThread {
//Фиксируем полученные данные
val List = listAppeals.body()
val Nice = listAppeals.isSuccessful
val Code = listAppeals.code()
if(Code==429){
val intetn = Intent(requireContext(), Code429Activity::class.java)
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
if(List.appeals_old != null){
// binding.txtNull.visibility = View.GONE
modelPatient.appealsOldList.value = List.appeals_old
}
else{
// binding.txtNull.visibility = View.VISIBLE
}
}else{
// binding.txtNull.visibility = View.VISIBLE
}
}
}
else if (Code == 500) {
val intetn = Intent(requireContext(), Code500Activity::class.java)
startActivity(intetn)
}
else if (Code == 401) {
val intetn = Intent(requireContext(), AuthorizationActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
}
} else {
val intetn = Intent(requireContext(), EnternetActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
//Получение необработанных сообщений
private fun addCheckAppeals(id:Int,id_patient:Int) {
if (enternetCheck.isOnline(requireContext())) {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val listAppeals = patientApi.UpdateMessagePatient("Bearer $Tokens",id)
requireActivity().runOnUiThread {
//Фиксируем полученные данные
val List = listAppeals.body()
val Nice = listAppeals.isSuccessful
val Code = listAppeals.code()
if(Code==429){
val intetn = Intent(requireContext(), Code429Activity::class.java)
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
Toast(requireContext()).showCustomInfoToast(List.message, requireActivity())
getNewAppeals()
getOldAppeals()
}
}
}
else if (Code == 500) {
val intetn = Intent(requireContext(), Code500Activity::class.java)
startActivity(intetn)
}
else if (Code == 401) {
val intetn = Intent(requireContext(), AuthorizationActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
}
} else {
val intetn = Intent(requireContext(), EnternetActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
//Инициализируем Retrofit
private fun initRetrofit() {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient
.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://rehabilitation.vmeda.org/api/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
patientApi = retrofit.create(PatientApi::class.java)
}
//Вывод прогресса на один день
private fun patientListCurrent() = with(binding) {
// model.appealsAllCurrent.observe(viewLifecycleOwner) {//viewLifecycleOwner - следит за циклом жизни fragment
//
// }
}
//Инициализация списка
private fun initRcViewAppeals() = with(binding) {
rcView.layoutManager = GridLayoutManager(requireContext(),1)//По вертикали будет выводить по умолчанию
adapter = AppealsNewAdapter(this@NewAppealsFragment,this@NewAppealsFragment)
rcView.adapter = adapter
}
companion object {
fun newInstance() = NewAppealsFragment()
}
override fun onClickAppeals(item: AppealsNewModel) {
addCheckAppeals(item.id,item.id_patient)
}
override fun onClickAppealsPatient(item: AppealsNewModel) {
}
}

View File

@ -0,0 +1,168 @@
package com.example.rehabilitation.Appeals.TabLayout
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.GridLayoutManager
import com.example.rehabilitation.Appeals.AppealsOldAdapter
import com.example.rehabilitation.Appeals.TabLayout.Model.AppealsNewModel
import com.example.rehabilitation.Appeals.TabLayout.Model.AppealsOldModel
import com.example.rehabilitation.Auth.AuthorizationActivity
import com.example.rehabilitation.CodeError.Code429Activity
import com.example.rehabilitation.CodeError.Code500Activity
import com.example.rehabilitation.Enternet.EnternetActivity
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.PatientViewModel
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.Retrofit.PatientApi
import com.example.rehabilitation.databinding.FragmentOldAppealsBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class OldAppealsFragment : Fragment(), AppealsOldAdapter.Listener {
private lateinit var binding: FragmentOldAppealsBinding
private val model: PatientViewModel by activityViewModels()
lateinit var adapter: AppealsOldAdapter
private lateinit var patientApi: PatientApi
val prefPatientConclusion = ConclusionPref()
//Класс проверки интеренета
val enternetCheck = EnternetCheck()
//Список обрашений старых
var appealsOldList: List<AppealsOldModel>? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentOldAppealsBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initRcViewAppeals()
appealsAllCurrent()
model.appealsOldList.observe(viewLifecycleOwner) {//viewLifecycleOwner - следит за циклом жизни fragment
if(appealsOldList != it){
appealsOldList = it
adapter.submitList(it)//Напрямую переадем созданный список в adapter(ProductAdapter)
}
}
getOldAppeals()
}
@SuppressLint("SuspiciousIndentation")
private fun getOldAppeals() {
if (enternetCheck.isOnline(requireContext())) {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val listAppeals = patientApi.GetAppealsPatientOld("Bearer $Tokens")
requireActivity().runOnUiThread {
//Фиксируем полученные данные
val List = listAppeals.body()
val Nice = listAppeals.isSuccessful
val Code = listAppeals.code()
if(Code==429){
val intetn = Intent(requireContext(), Code429Activity::class.java)
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
if(List.appeals_old != null){
binding.txtNull.visibility = View.GONE
model.appealsOldList.value = List.appeals_old
}
else{
binding.txtNull.visibility = View.VISIBLE
}
}else{
binding.txtNull.visibility = View.VISIBLE
}
}
}
else if (Code == 500) {
val intetn = Intent(requireContext(), Code500Activity::class.java)
startActivity(intetn)
}
else if (Code == 401) {
val intetn = Intent(requireContext(), AuthorizationActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
}
} else {
val intetn = Intent(requireContext(), EnternetActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
//Инициализируем Retrofit
private fun initRetrofit() {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient
.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://rehabilitation.vmeda.org/api/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
patientApi = retrofit.create(PatientApi::class.java)
}
//Вывод прогресса на один день
private fun appealsAllCurrent() = with(binding) {
// model.appealsAllCurrent.observe(viewLifecycleOwner) {//viewLifecycleOwner - следит за циклом жизни fragment
//
// }
}
//Инициализация списка
private fun initRcViewAppeals() = with(binding) {
rcView.layoutManager = GridLayoutManager(requireContext(),1)//По вертикали будет выводить по умолчанию
adapter = AppealsOldAdapter(this@OldAppealsFragment)
rcView.adapter = adapter
}
companion object {
fun newInstance() = OldAppealsFragment()
}
override fun onClickAppeals(item: AppealsOldModel) {
}
}

View File

@ -0,0 +1,175 @@
package com.example.rehabilitation.Auth
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.activityViewModels
import com.example.admin.Toast.showCustomInfoToast
import com.example.rehabilitation.Auth.Model.AuthModel
import com.example.rehabilitation.CodeError.Code429Activity
import com.example.rehabilitation.CodeError.Code500Activity
import com.example.rehabilitation.MainActivity
import com.example.rehabilitation.databinding.FragmentAuthBinding
import com.example.rehabilitation.UserPatientToken
import com.example.rehabilitation.Enternet.EnternetActivity
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.MainFragment
import com.example.rehabilitation.PatientViewModel
import com.example.rehabilitation.Pref.ClearPref
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.Pref.SavePref
import com.example.rehabilitation.Questionnaire.Model.BeforeQuestionnaireModel
import com.example.rehabilitation.R
import com.example.rehabilitation.Retrofit.PatientApi
import com.example.rehabilitation.Sport.SceduleFragment
import com.example.sqlitework.dip.MainViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
/**
* Фрагмент авторизации пациента
* Отвечает за вход в систему и проверку учетных данных
*/
class AuthFragment : Fragment() {
// Привязка к layout файлу
private lateinit var binding: FragmentAuthBinding
// ViewModel для работы с основными данными
private val model: MainViewModel by activityViewModels()
// API для работы с данными пациента
private lateinit var patientApi: PatientApi
// ViewModel для работы с данными пациента
private val PatientVewModel: PatientViewModel by activityViewModels()
// Токен авторизации
private var Token = ""
// Классы для работы с настройками
val prefPatientSave = SavePref()
val prefPatientConclusion = ConclusionPref()
val prefPatientClear = ClearPref()
// Класс для проверки интернет-соединения
val enternetCheck = EnternetCheck()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentAuthBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.txtError.text = ""
Token = prefPatientConclusion.conclusionToken(requireContext())
// Обработчик нажатия кнопки авторизации
binding.buttonAuthorizationPatient.setOnClickListener {
val login = binding.editTextLoginPatient.text.toString()
val password = binding.editTextPasswordPatient.text.toString()
if (login != "" || password != "") {
AuthorizationPatient(
AuthModel(
login,
password,
)
)
} else {
Toast(requireContext()).showCustomInfoToast(
"Не все поля заполнены",
requireActivity()
)
}
}
}
/**
* Инициализация подключения к серверу
* Настройка Retrofit для работы с API
*/
private fun initRetrofit() {
// Настройка логирования
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
// Создание HTTP клиента
val client = OkHttpClient
.Builder()
.addInterceptor(interceptor)
.build()
// Инициализация Retrofit
val retrofit = Retrofit.Builder()
.baseUrl("https://rehabilitation.vmeda.org/api/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
patientApi = retrofit.create(PatientApi::class.java)
}
/**
* Авторизация пациента
* @param authModel Модель с данными для авторизации (логин и пароль)
*/
private fun AuthorizationPatient(authModel: AuthModel) {
if (enternetCheck.isOnline(requireContext())) {
initRetrofit()
CoroutineScope(Dispatchers.IO).launch {
val response = patientApi.LoginPatient(authModel)
requireActivity().runOnUiThread {
// Обработка ответа от сервера
val List = response.body()
val Nice = response.isSuccessful
val Code = response.code()
when (Code) {
429 -> {
// Слишком много запросов
val intetn = Intent(requireContext(), Code429Activity::class.java)
startActivity(intetn)
}
200 -> {
// Успешный ответ
if (Nice) {
if (List != null) {
// Сохранение токена и переход на главный экран
prefPatientSave.saveToken(requireContext(), List.token)
val intetn = Intent(requireContext(), MainActivity::class.java)
startActivity(intetn)
} else {
Toast(requireContext()).showCustomInfoToast(
"Такого пользователя нету",
requireActivity()
)
}
}
}
}
}
}
} else {
// Нет интернет-соединения
val intetn = Intent(requireContext(), EnternetActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
override fun onDestroy() {
super.onDestroy()
activity?.finish()
}
companion object {
fun newInstance() = AuthFragment()
}
}

View File

@ -0,0 +1,30 @@
package com.example.rehabilitation.Auth
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.rehabilitation.R
import com.example.rehabilitation.databinding.ActivityAuthorizationBinding
class AuthorizationActivity : AppCompatActivity() {
private lateinit var binding: ActivityAuthorizationBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAuthorizationBinding.inflate(layoutInflater)
setContentView(binding.root)
//Вывод фрагмента на активити при первоначальной загрузке
supportFragmentManager.beginTransaction()
.replace(R.id.CLAuth, AuthFragment.newInstance())
.commit()//Заменяем наш экран на фрагмент (используем наш экран как основу)//R.id.placeHolder - куда всталяем //MainFragment.newInstance() - это то что мы вставляем
}
}

View File

@ -0,0 +1,7 @@
package com.example.rehabilitation.Auth.Model
data class AuthModel(
val login: String,
val password: String,
)

View File

@ -0,0 +1,5 @@
package com.example.rehabilitation.Auth.Model
data class CheckTokenModel(
val status:String,
)

View File

@ -0,0 +1,14 @@
package com.example.rehabilitation.Auth.Model
data class PatientModel(
val id: String,
val name:String,
val surname:String,
val patronymic:String,
val diagnosis:String,
val number_of_courses:String,
//val email:String,
val login:String,
val password:String,
)

View File

@ -0,0 +1,7 @@
package com.example.rehabilitation.Auth.Model
data class UserModel(
val id: String,
val token: String,
)

View File

@ -0,0 +1,130 @@
package com.example.rehabilitation
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import com.example.rehabilitation.databinding.FragmentAuthBinding
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.Toast.showErrorToast
import com.example.rehabilitation.Toast.showSuccessToast
/**
* Фрагмент авторизации пользователя
* Отвечает за вход в систему и сохранение данных авторизации
*/
class AuthFragment : Fragment() {
// ViewBinding для доступа к элементам интерфейса
private var _binding: FragmentAuthBinding? = null
private val binding get() = _binding!!
// ViewModel для работы с данными авторизации
private lateinit var viewModel: AuthViewModel
// Класс для работы с настройками
private lateinit var conclusionPref: ConclusionPref
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentAuthBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Инициализация ViewModel и настроек
viewModel = ViewModelProvider(this)[AuthViewModel::class.java]
conclusionPref = ConclusionPref()
// Настройка обработчиков нажатий
setupClickListeners()
// Наблюдение за изменениями данных
observeViewModel()
}
/**
* Настройка обработчиков нажатий
*/
private fun setupClickListeners() {
// Обработка нажатия кнопки входа
binding.btnLogin.setOnClickListener {
val login = binding.etLogin.text.toString()
val password = binding.etPassword.text.toString()
if (validateInput(login, password)) {
viewModel.login(login, password)
}
}
// Обработка нажатия кнопки регистрации
binding.btnRegister.setOnClickListener {
findNavController().navigate(R.id.action_authFragment_to_registerFragment)
}
}
/**
* Проверка введенных данных
* @param login Логин пользователя
* @param password Пароль пользователя
* @return true если данные валидны, false в противном случае
*/
private fun validateInput(login: String, password: String): Boolean {
if (login.isEmpty()) {
showErrorToast(requireContext(), "Введите логин")
return false
}
if (password.isEmpty()) {
showErrorToast(requireContext(), "Введите пароль")
return false
}
return true
}
/**
* Наблюдение за изменениями данных в ViewModel
*/
private fun observeViewModel() {
// Наблюдение за статусом загрузки
viewModel.isLoading.observe(viewLifecycleOwner) { isLoading ->
binding.progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
binding.btnLogin.isEnabled = !isLoading
}
// Наблюдение за результатом авторизации
viewModel.authResult.observe(viewLifecycleOwner) { result ->
result?.let {
if (it.success) {
// Сохранение данных авторизации
conclusionPref.saveToken(requireContext(), it.token)
conclusionPref.saveUserId(requireContext(), it.userId)
conclusionPref.saveLoginStatus(requireContext(), true)
showSuccessToast(requireContext(), "Успешный вход")
findNavController().navigate(R.id.action_authFragment_to_mainFragment)
} else {
showErrorToast(requireContext(), it.message)
}
}
}
// Наблюдение за ошибками
viewModel.error.observe(viewLifecycleOwner) { error ->
error?.let {
showErrorToast(requireContext(), it)
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -0,0 +1,251 @@
package com.example.rehabilitation.Calendare
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.GridLayoutManager
import com.example.rehabilitation.Auth.AuthorizationActivity
import com.example.rehabilitation.CodeError.Code429Activity
import com.example.rehabilitation.CodeError.Code500Activity
import com.example.rehabilitation.Enternet.EnternetActivity
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.PatientViewModel
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.Retrofit.PatientApi
import com.example.rehabilitation.Sport.DayAdapter
import com.example.rehabilitation.databinding.FragmentCalendarBinding
import com.example.sqlitework.dip.MainViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.time.LocalDate
import java.util.Timer
import kotlin.concurrent.fixedRateTimer
import kotlin.concurrent.timerTask
class CalendarFragment : Fragment(),CalendareListAdapter.Listener {
private lateinit var binding: FragmentCalendarBinding
lateinit var adapterCalendare: CalendareListAdapter
private val modelPatient: PatientViewModel by activityViewModels()//Инициализировали класс
private lateinit var patientApi: PatientApi
private lateinit var timer: Timer
val prefPatientConclusion = ConclusionPref()
//Календарь
var listCalendare:List<CalendareModel>? = null
@SuppressLint("NewApi")
//Загрузка данных для календаря
var calendare = false
//Класс проверки интеренета
val enternetCheck = EnternetCheck()
var infoVisibleCalendare = false
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentCalendarBinding.inflate(layoutInflater, container, false)
return binding.root
}
@SuppressLint("NewApi")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if(isAdded) {
visibleLoad()
initRcView()
initRetrofit()
APIliveCountCalendareCurrent()
modelPatient.calendareList.observe(viewLifecycleOwner){
if(listCalendare != it){
listCalendare = it
adapterCalendare.submitList(it)
}
visibleCalendare()
}
// fixedRateTimer("timer", false, 0, 10000) {
// activity?.runOnUiThread {
//
// }
// }
}
// Устанавливаем обработчик нажатий на корневой контейнер
binding.root.setOnTouchListener { _, _ ->
if (infoVisibleCalendare) {
infoVisibleCalendare = false
binding.CVInfoCalendare.visibility = View.GONE
}
false // Событие передаётся дальше
}
// Открытие и закрытие подсказки по кнопке
binding.btnInfoCalendare.setOnClickListener {
if (!infoVisibleCalendare) {
infoVisibleCalendare = true
binding.CVInfoCalendare.visibility = View.VISIBLE
} else {
infoVisibleCalendare = false
binding.CVInfoCalendare.visibility = View.GONE
}
}
}
fun visibleCalendare(){
binding.CLCalendare.visibility = View.VISIBLE
binding.CLLoad.visibility = View.GONE
}
fun visibleLoad(){
binding.CLCalendare.visibility = View.GONE
binding.CLLoad.visibility = View.VISIBLE
}
//Инициализация списка
private fun initRcView() = with(binding) {
rcView.layoutManager = GridLayoutManager(requireContext(), 1)//По вертикали будет выводить по умолчанию
adapterCalendare = CalendareListAdapter(this@CalendarFragment)
rcView.adapter = adapterCalendare
//binding.rcVIewDayList.smoothScrollToPosition(0);
}
//Инициализация запроса
private fun initRetrofit() {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient
.Builder()
.addInterceptor(interceptor)
.build()
//Базовая ссылка
val retrofit = Retrofit.Builder()
.baseUrl("https://rehabilitation.vmeda.org/api/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
patientApi = retrofit.create(PatientApi::class.java)//Экземпляр
}
//Функция получения данных для заполнения календаря
private fun APIliveCountCalendareCurrent() {
if (enternetCheck.isOnline(requireContext())) {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val Calendare = patientApi.GetCalendare("Bearer $Tokens")
activity?.runOnUiThread {
//Фиксируем полученные данные
val List = Calendare.body()
val Nice = Calendare.isSuccessful
val Code = Calendare.code()
if(Code==429){
val intetn = Intent(requireContext(), Code429Activity::class.java)
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
Log.i("CalendareList_calendare_day", List.calendare_day.toString())
modelPatient.calendareList.value = List.calendare_day
}
}
}
else if (Code == 500) {
val intetn = Intent(requireContext(), Code500Activity::class.java)
startActivity(intetn)
}
else if (Code == 401) {
val intetn = Intent(requireContext(), AuthorizationActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
}
} else {
val intetn = Intent(requireContext(), EnternetActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
companion object {
fun newInstance() = CalendarFragment()
}
override fun onClickCalendare(item: CalendareModel) {
}
override fun onResume() {
super.onResume()
checkForUpdates(true)
}
override fun onStop() {
super.onStop()
timer.cancel()
timer.purge()
}
private fun checkForUpdates(daemonIsTrue: Boolean) {
timer = fixedRateTimer("default", daemonIsTrue, 0, 15000) {
activity?.runOnUiThread {
APIliveCountCalendareCurrent()
}
}
}
}

View File

@ -0,0 +1,123 @@
package com.example.rehabilitation.Calendare
import android.annotation.SuppressLint
import android.graphics.Color
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.rehabilitation.R
import com.example.rehabilitation.databinding.ItemCalendareBinding
import java.time.LocalDate
class CalendareListAdapter(val listener: Listener) :
ListAdapter<CalendareModel, CalendareListAdapter.Holder>(
Comparator()
) {//Productitem - по этой форме будем заполнять.//ProductAdapter.holder - это создаваемый holder который хранит логику как нужно заполнять карточку
//В holder создаетс код с помошью которого мы будем заполнять и сохронять разметку
class Holder(view: View, val listener: Listener) :
RecyclerView.ViewHolder(view) {//Класс который будет хранить сссылки на элементы, и отвечает за один элемент за 1 раз, то есть сначсало нулевой элемент заполнит, потом первый, потом второй и т.д.
//Для передачи данных
val binding = ItemCalendareBinding.bind(view)//view - здесь храянтся элементы и мы их bind заполним в ListItemBinding//ListItemBinding - это клласс даннйо разметки(карточки) которую мы будем заполнять, а нужна дання переменная(binding), чтобы мжно было при заполнение обращатся к элементам карточки
var itemTemp: CalendareModel? =
null//Глобальная переменная для нашего item, чтобы можно было передать данные для нажатия
//init - дает возможность внутри адаптера обращаться к элементам экрана
init {
itemView.setOnClickListener {//Нажатие на ячейку//itemView - это весь элемент карточки из списка
//itemView.setEnabled(false)
itemTemp?.let { it1 -> listener.onClickCalendare(it1) }
}
}
@SuppressLint("SuspiciousIndentation", "SetTextI18n")
fun bind(item: CalendareModel) = with(binding) {//Productitem - перпедаем данные
itemTemp = item
txtDay.text = item.day
val date1 = item.date[8];
val date2 = item.date[9];
val date3 = item.date[5];
val date4 = item.date[6];
val date5 = item.date[0];
val date6 = item.date[1];
val date7 = item.date[2];
val date8 = item.date[3];
txtDate.text = date1+""+date2+"."+date3+""+date4+"."+date5+""+date6+""+date7+""+date8
if(item.block != null){
binding.CVBlock.setCardBackgroundColor(Color.parseColor("#FF0000"))
}
else if(item.pause != null){
binding.CVPause.setCardBackgroundColor(Color.parseColor("#FFA355"))
}
if(item.id_after_questionnaire != null){
binding.CVDay.setCardBackgroundColor(Color.parseColor("#7FE668"))
}
else{
if(item.block == null){
if(item.date >= LocalDate.now().toString()){
binding.CVDay.setCardBackgroundColor(Color.parseColor("#55B6FF"))
}
else{
binding.CVDay.setCardBackgroundColor(Color.parseColor("#9C9C9C"))
}
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_calendare, parent, false)//Создаем(надуваем) list_item
return Holder(view, listener)//Через Holder возврощаем view
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val view = holder.bind(getItem(position))//Заполняем по позиции карточку
}
//Comparator - сравнивает старый список и новый и если что-то изменилось, то работает с конкретным изменением списке, а не весь список переписывает
class Comparator : DiffUtil.ItemCallback<CalendareModel>() {
override fun areItemsTheSame(
oldItem: CalendareModel,
newItem: CalendareModel
): Boolean {//Тут лучше всего сравнивать по id//oldItem - элементы старого списка, newItem - элементы нового списка//Возврощает Boolean, тоесть есть изменения или нет
return oldItem.id == newItem.id//Сравниваем полностью весь список новы и старый, по очередно по одной карточке и по элементно, то есть нулевой элемент, первый, второй и т.д.. Но лучше сравнивать по id списки, а не просто весь список, так как это эфективнее, так как id уникальный(oldItem.id == newItem.id)
}
override fun areContentsTheSame(
oldItem: CalendareModel,
newItem: CalendareModel
): Boolean {//Утут нужно сравнивать весь спсок старых элементов и новых
return oldItem == newItem//Сравниваем полностью весь список новы и старый
}
}
//Интерфейс нажатия на кнопку удалить товар из корзины
interface Listener {
fun onClickCalendare(item: CalendareModel)
}
}

View File

@ -0,0 +1,5 @@
package com.example.rehabilitation.Calendare
data class CalendareListModel(
val calendare_day: List<CalendareModel>
)

View File

@ -0,0 +1,19 @@
package com.example.rehabilitation.Calendare
data class CalendareModel(
val id: Int,
val id_patient : Int,
val day: String,
val date: String,
val count_workout_max:Int,
val count_workout_make: Int,
val id_sets_of_sports_activities : Int,
val article_sport_for_day: String,
val id_sport_patient :Int,
val block: String,
val pause: String,
val id_before_questionnaire : String,
val id_after_questionnaire : String,
val created_at : String,
val updated_at : String,
)

View File

@ -0,0 +1,68 @@
package com.example.rehabilitation
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import com.example.rehabilitation.databinding.ActivityCode429Binding
/**
* Активность, отображаемая при получении ошибки 429 (Too Many Requests)
* Информирует пользователя о превышении лимита запросов и предлагает повторить попытку позже
*/
class Code429Activity : AppCompatActivity() {
// ViewBinding для безопасного доступа к UI элементам
private lateinit var binding: ActivityCode429Binding
// Обработчик для обновления UI
private val handler = Handler(Looper.getMainLooper())
// Задержка между проверками (в миллисекундах)
private val CHECK_DELAY = 5000L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCode429Binding.inflate(layoutInflater)
setContentView(binding.root)
// Настройка обработчиков нажатий
setupClickListeners()
// Запуск периодической проверки
startRetryCheck()
}
/**
* Настройка обработчиков нажатий на кнопки
*/
private fun setupClickListeners() {
// Обработчик нажатия на кнопку "Повторить"
binding.retryButton.setOnClickListener {
finish()
}
// Обработчик нажатия на кнопку "Выход"
binding.exitButton.setOnClickListener {
finish()
}
}
/**
* Запуск периодической проверки возможности повторного запроса
*/
private fun startRetryCheck() {
handler.postDelayed(object : Runnable {
override fun run() {
// По истечении задержки возвращаемся к предыдущей активности
finish()
handler.postDelayed(this, CHECK_DELAY)
}
}, CHECK_DELAY)
}
override fun onDestroy() {
super.onDestroy()
// Останавливаем периодическую проверку при уничтожении активности
handler.removeCallbacksAndMessages(null)
}
}

View File

@ -0,0 +1,68 @@
package com.example.rehabilitation
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import com.example.rehabilitation.databinding.ActivityCode500Binding
/**
* Активность, отображаемая при получении ошибки 500 (Internal Server Error)
* Информирует пользователя о внутренней ошибке сервера и предлагает повторить попытку позже
*/
class Code500Activity : AppCompatActivity() {
// ViewBinding для безопасного доступа к UI элементам
private lateinit var binding: ActivityCode500Binding
// Обработчик для обновления UI
private val handler = Handler(Looper.getMainLooper())
// Задержка между проверками (в миллисекундах)
private val CHECK_DELAY = 5000L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCode500Binding.inflate(layoutInflater)
setContentView(binding.root)
// Настройка обработчиков нажатий
setupClickListeners()
// Запуск периодической проверки
startRetryCheck()
}
/**
* Настройка обработчиков нажатий на кнопки
*/
private fun setupClickListeners() {
// Обработчик нажатия на кнопку "Повторить"
binding.retryButton.setOnClickListener {
finish()
}
// Обработчик нажатия на кнопку "Выход"
binding.exitButton.setOnClickListener {
finish()
}
}
/**
* Запуск периодической проверки возможности повторного запроса
*/
private fun startRetryCheck() {
handler.postDelayed(object : Runnable {
override fun run() {
// По истечении задержки возвращаемся к предыдущей активности
finish()
handler.postDelayed(this, CHECK_DELAY)
}
}, CHECK_DELAY)
}
override fun onDestroy() {
super.onDestroy()
// Останавливаем периодическую проверку при уничтожении активности
handler.removeCallbacksAndMessages(null)
}
}

View File

@ -0,0 +1,227 @@
package com.example.rehabilitation.CodeError
import android.annotation.SuppressLint
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.CountDownTimer
import android.util.Log
import com.example.rehabilitation.Auth.AuthorizationActivity
import com.example.rehabilitation.Enternet.EnternetActivity
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.MainActivity
import com.example.rehabilitation.Pref.ClearPref
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.Pref.SavePref
import com.example.rehabilitation.Retrofit.PatientApi
import com.example.rehabilitation.databinding.ActivityCode429Binding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.Timer
import kotlin.concurrent.fixedRateTimer
import android.widget.Toast
import com.example.admin.Toast.showCustomInfoToast
import com.example.rehabilitation.R
import android.os.Handler
import android.os.Looper
import android.view.View
/**
* Активность, отображаемая при превышении лимита запросов к серверу (код ошибки 429)
* Предоставляет пользователю информацию о проблеме и возможность повторить попытку
*/
class Code429Activity : AppCompatActivity() {
// ViewBinding для доступа к элементам интерфейса
private lateinit var binding: ActivityCode429Binding
private lateinit var patientApi: PatientApi
private lateinit var timer: Timer
// Обработчик для обновления таймера
private val handler = Handler(Looper.getMainLooper())
// Время ожидания в секундах
private var remainingTime = 30
// Runnable для обновления таймера
private val updateTimerRunnable = object : Runnable {
override fun run() {
updateTimer()
}
}
val prefPatientConclusion = ConclusionPref()
val prefPatientClear = ClearPref()
val prefPatientSave = SavePref()
//Класс проверки интеренета
val enternetCheck = EnternetCheck()
var checkClose = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCode429Binding.inflate(layoutInflater)
setContentView(binding.root)
// Настройка обработчиков нажатий
setupClickListeners()
// Запуск таймера
startTimer()
}
/**
* Настройка обработчиков нажатий
*/
private fun setupClickListeners() {
// Обработка нажатия кнопки повтора
binding.btnRetry.setOnClickListener {
// Возвращаемся на главный экран
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}
// Обработка нажатия кнопки выхода
binding.btnExit.setOnClickListener {
// Закрываем приложение
finishAffinity()
}
}
override fun onBackPressed() {
// Отключаем стандартное поведение кнопки "Назад"
// Пользователь должен явно выбрать действие через кнопки на экране
Toast(this).showCustomInfoToast(
"Пожалуйста, используйте кнопки на экране",
this
)
}
@SuppressLint("SuspiciousIndentation")
fun CheckToken()=with(binding){
if (enternetCheck.isOnline(this@Code429Activity)) {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(this@Code429Activity)
CoroutineScope(Dispatchers.IO).launch {
val list = patientApi.CheckToken("Bearer $Tokens")
runOnUiThread {
//Фиксируем полученные данные
val List = list.body()
val Nice = list.isSuccessful
val Code = list.code()
if(Code==500){
val intetn = Intent(this@Code429Activity, Code500Activity::class.java)
finish()
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
Log.i("clogon1231111","clogon1231111")
finish()
}
}
}
else if (Code == 401) {
val intetn = Intent(this@Code429Activity, AuthorizationActivity::class.java)
finish()
startActivity(intetn)
}
}
}
} else {
val intetn = Intent(this@Code429Activity, EnternetActivity::class.java)
finish()
startActivity(intetn)
}
}
//Инициализируем Retrofit
private fun initRetrofit() {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient
.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://rehabilitation.vmeda.org/api/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
patientApi = retrofit.create(PatientApi::class.java)
}
override fun onResume() {
super.onResume()
checkForUpdates(true)
}
override fun onStop() {
super.onStop()
timer.cancel()
timer.purge()
}
private fun checkForUpdates(daemonIsTrue: Boolean) {
timer = fixedRateTimer("default", daemonIsTrue, 0, 15000) {
this@Code429Activity.runOnUiThread {
CheckToken()
}
}
}
/**
* Запуск таймера обратного отсчета
*/
private fun startTimer() {
binding.apply {
tvTimer.visibility = View.VISIBLE
btnRetry.isEnabled = false
}
handler.post(updateTimerRunnable)
}
/**
* Обновление таймера
*/
private fun updateTimer() {
if (remainingTime > 0) {
binding.tvTimer.text = getString(R.string.retry_after_seconds, remainingTime)
remainingTime--
handler.postDelayed(updateTimerRunnable, 1000)
} else {
binding.apply {
tvTimer.visibility = View.GONE
btnRetry.isEnabled = true
}
}
}
override fun onDestroy() {
super.onDestroy()
// Остановка таймера при уничтожении активности
handler.removeCallbacks(updateTimerRunnable)
}
}

View File

@ -0,0 +1,235 @@
package com.example.rehabilitation.CodeError
import android.annotation.SuppressLint
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.CountDownTimer
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.core.content.ContentProviderCompat.requireContext
import com.example.rehabilitation.Auth.AuthorizationActivity
import com.example.rehabilitation.Enternet.EnternetActivity
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.MainActivity
import com.example.rehabilitation.Pref.ClearPref
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.Pref.SavePref
import com.example.rehabilitation.Retrofit.PatientApi
import com.example.rehabilitation.databinding.ActivityCode500Binding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.Timer
import kotlin.concurrent.fixedRateTimer
import com.example.admin.Toast.showCustomInfoToast
import com.example.rehabilitation.R
import com.example.rehabilitation.Toast.showErrorToast
import com.example.rehabilitation.Toast.showSuccessToast
/**
* Активность, отображаемая при ошибке сервера (HTTP 500)
* Показывает пользователю информацию об ошибке и предоставляет варианты действий
*/
class Code500Activity : AppCompatActivity() {
// ViewBinding для безопасного доступа к UI элементам
private lateinit var binding: ActivityCode500Binding
private lateinit var patientApi: PatientApi
private lateinit var timer: Timer
val prefPatientConclusion = ConclusionPref()
val prefPatientClear = ClearPref()
val prefPatientSave = SavePref()
//Класс проверки интеренета
val enternetCheck = EnternetCheck()
var checkClose = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCode500Binding.inflate(layoutInflater)
setContentView(binding.root)
// Настройка обработчиков нажатий
setupClickListeners()
// Отображение информации об ошибке
showErrorInfo()
binding.apply {
val timer = object: CountDownTimer(30000, 1000) {
override fun onTick(millisUntilFinished: Long) {
}
override fun onFinish() {
val intetn = Intent(this@Code500Activity, AuthorizationActivity::class.java)
finish()
startActivity(intetn)
}
}
timer.start()
}
}
/**
* Настройка обработчиков нажатий на кнопки
*/
private fun setupClickListeners() {
// Обработчик нажатия на кнопку "Повторить"
binding.btnRetry.setOnClickListener {
retryOperation()
}
// Обработчик нажатия на кнопку "Выход"
binding.btnExit.setOnClickListener {
finishAffinity()
}
// Обработчик нажатия на кнопку "Отправить отзыв"
binding.btnFeedback.setOnClickListener {
sendFeedback()
}
}
/**
* Отображение информации об ошибке
*/
private fun showErrorInfo() {
binding.apply {
// Установка иконки ошибки
ivError.setImageResource(R.drawable.ic_server_error)
// Установка заголовка
tvTitle.text = getString(R.string.server_error_title)
// Установка описания ошибки
tvDescription.text = getString(R.string.server_error_description)
// Установка рекомендаций
tvRecommendation.text = getString(R.string.server_error_recommendation)
}
}
/**
* Повторная попытка выполнения операции
*/
private fun retryOperation() {
binding.apply {
// Показ индикатора загрузки
progressBar.visibility = View.VISIBLE
// Отключение кнопки повтора
btnRetry.isEnabled = false
// TODO: Реализовать повторную попытку выполнения операции
// Скрытие индикатора загрузки
progressBar.visibility = View.GONE
// Включение кнопки повтора
btnRetry.isEnabled = true
}
}
/**
* Отправка отзыва об ошибке
*/
private fun sendFeedback() {
// TODO: Реализовать отправку отзыва
showSuccessToast(this, "Спасибо за обратную связь!")
}
override fun onBackPressed() {
// Отключаем стандартное поведение кнопки "Назад"
// Пользователь должен явно выбрать действие через кнопки на экране
Toast(this).showCustomInfoToast(
"Пожалуйста, используйте кнопки на экране",
this
)
}
@SuppressLint("SuspiciousIndentation")
fun CheckToken()=with(binding){
if (enternetCheck.isOnline(this@Code500Activity)) {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(this@Code500Activity)
CoroutineScope(Dispatchers.IO).launch {
val list = patientApi.CheckToken("Bearer $Tokens")
runOnUiThread {
//Фиксируем полученные данные
val List = list.body()
val Nice = list.isSuccessful
val Code = list.code()
if(Code==429){
val intetn = Intent(this@Code500Activity, Code429Activity::class.java)
finish()
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
Log.i("clogon1231111","clogon1231111")
finish()
}
}
}
else if (Code == 401) {
val intetn = Intent(this@Code500Activity, AuthorizationActivity::class.java)
finish()
startActivity(intetn)
}
}
}
} else {
val intetn = Intent(this@Code500Activity, EnternetActivity::class.java)
finish()
startActivity(intetn)
}
}
//Инициализируем Retrofit
private fun initRetrofit() {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient
.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://rehabilitation.vmeda.org/api/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
patientApi = retrofit.create(PatientApi::class.java)
}
override fun onResume() {
super.onResume()
checkForUpdates(true)
}
override fun onStop() {
super.onStop()
timer.cancel()
timer.purge()
}
private fun checkForUpdates(daemonIsTrue: Boolean) {
timer = fixedRateTimer("default", daemonIsTrue, 0, 10000) {
this@Code500Activity.runOnUiThread {
CheckToken()
}
}
}
}

View File

@ -0,0 +1,76 @@
package com.example.rehabilitation.Enternet
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.admin.Toast.showCustomInfoToast
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.MainActivity
import com.example.rehabilitation.R
import com.example.rehabilitation.databinding.ActivityEnternetBinding
/**
* Активность, отображаемая при отсутствии интернет-соединения
* Предоставляет пользователю информацию о проблеме и возможность повторить подключение
*/
class EnternetActivity : AppCompatActivity() {
// Привязка к layout файлу
private lateinit var binding: ActivityEnternetBinding
// Класс для проверки интернет-соединения
private val enternetCheck = EnternetCheck()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityEnternetBinding.inflate(layoutInflater)
setContentView(binding.root)
// Инициализация обработчиков кнопок
initButtons()
}
/**
* Инициализация обработчиков кнопок
*/
private fun initButtons() {
// Обработчик кнопки повтора подключения
binding.btnRetry.setOnClickListener {
if (enternetCheck.isOnline(this)) {
// Если соединение восстановлено, возвращаемся на главный экран
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
} else {
// Если соединение все еще отсутствует, показываем сообщение
Toast(this).showCustomInfoToast(
"Проверьте подключение к интернету",
this
)
}
}
// Обработчик кнопки выхода
binding.btnExit.setOnClickListener {
// Закрываем приложение
finishAffinity()
}
}
override fun onResume() {
super.onResume()
// Проверяем состояние соединения при возобновлении активности
checkConnection()
}
/**
* Проверка состояния интернет-соединения
*/
private fun checkConnection() {
if (enternetCheck.isOnline(this)) {
// Если соединение восстановлено, возвращаемся на главный экран
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}
}
}

View File

@ -0,0 +1,78 @@
package com.example.rehabilitation.Enternet
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
/**
* Класс для проверки состояния интернет-соединения
* Предоставляет методы для определения доступности сети и типа подключения
*/
class EnternetCheck() {
//Проверка интернета
fun isOnline(context: Context): Boolean {
if (context == null) return false
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val capabilities =
connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
if (capabilities != null) {
when {
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
return true
}
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
return true
}
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> {
return true
}
}
}
} else {
val activeNetworkInfo = connectivityManager.activeNetworkInfo
if (activeNetworkInfo != null && activeNetworkInfo.isConnected) {
return true
}
}
return false
}
/**
* Проверяет тип активного интернет-соединения
* @param context Контекст приложения
* @return Строка с описанием типа подключения или "Нет подключения"
*/
fun getConnectionType(context: Context): String {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return "Нет подключения"
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return "Нет подключения"
return when {
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> "Wi-Fi"
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> "Мобильная сеть"
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> "Ethernet"
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> "Bluetooth"
else -> "Неизвестное подключение"
}
}
/**
* Проверяет качество интернет-соединения
* @param context Контекст приложения
* @return true если соединение стабильное, false в противном случае
*/
fun isConnectionStable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
}

View File

@ -0,0 +1,38 @@
package com.example.rehabilitation.Enternet
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.MainActivity
import com.example.rehabilitation.databinding.FragmentEnternetBinding
class EnternetFragment : Fragment() {
private lateinit var binding: FragmentEnternetBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentEnternetBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnEnternet.setOnClickListener{
val intetn = Intent(requireContext(), MainActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
companion object {
fun newInstance() = EnternetFragment()
}
}

View File

@ -0,0 +1,82 @@
package com.example.rehabilitation
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import com.example.rehabilitation.databinding.ActivityEnternetBinding
import com.example.rehabilitation.EnternetCheck.ConnectionType
import com.example.rehabilitation.EnternetCheck.getConnectionType
import com.example.rehabilitation.EnternetCheck.isInternetAvailable
/**
* Активность, отображаемая при отсутствии подключения к интернету
* Предоставляет пользователю информацию о проблеме и возможность повторить проверку
*/
class EnternetActivity : AppCompatActivity() {
// ViewBinding для безопасного доступа к UI элементам
private lateinit var binding: ActivityEnternetBinding
// Обработчик для обновления UI
private val handler = Handler(Looper.getMainLooper())
// Задержка между проверками подключения (в миллисекундах)
private val CHECK_DELAY = 2000L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityEnternetBinding.inflate(layoutInflater)
setContentView(binding.root)
// Настройка обработчиков нажатий
setupClickListeners()
// Запуск периодической проверки подключения
startConnectionCheck()
}
/**
* Настройка обработчиков нажатий на кнопки
*/
private fun setupClickListeners() {
// Обработчик нажатия на кнопку "Повторить"
binding.retryButton.setOnClickListener {
checkConnection()
}
// Обработчик нажатия на кнопку "Выход"
binding.exitButton.setOnClickListener {
finish()
}
}
/**
* Запуск периодической проверки подключения
*/
private fun startConnectionCheck() {
handler.postDelayed(object : Runnable {
override fun run() {
checkConnection()
handler.postDelayed(this, CHECK_DELAY)
}
}, CHECK_DELAY)
}
/**
* Проверка подключения к интернету
*/
private fun checkConnection() {
if (EnternetCheck.isInternetAvailable(this)) {
// Если подключение восстановлено, возвращаемся к предыдущей активности
finish()
}
}
override fun onDestroy() {
super.onDestroy()
// Останавливаем периодическую проверку при уничтожении активности
handler.removeCallbacksAndMessages(null)
}
}
}

View File

@ -0,0 +1,90 @@
package com.example.rehabilitation
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
/**
* Объект для проверки состояния сетевого подключения
* Предоставляет методы для проверки доступности интернета и типа подключения
*/
object EnternetCheck {
/**
* Проверка наличия подключения к интернету
* @param context Контекст приложения
* @return true, если есть активное подключение к интернету, false в противном случае
*/
fun isInternetAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
/**
* Получение типа подключения к интернету
* @param context Контекст приложения
* @return Тип подключения (WiFi, Cellular, None)
*/
fun getConnectionType(context: Context): ConnectionType {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val network = connectivityManager.activeNetwork ?: return ConnectionType.NONE
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return ConnectionType.NONE
return when {
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> ConnectionType.WIFI
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> ConnectionType.CELLULAR
else -> ConnectionType.NONE
}
} else {
@Suppress("DEPRECATION")
val networkInfo = connectivityManager.activeNetworkInfo
@Suppress("DEPRECATION")
return when (networkInfo?.type) {
ConnectivityManager.TYPE_WIFI -> ConnectionType.WIFI
ConnectivityManager.TYPE_MOBILE -> ConnectionType.CELLULAR
else -> ConnectionType.NONE
}
}
}
/**
* Проверка типа подключения (Wi-Fi)
* @param context Контекст приложения
* @return true, если подключение осуществляется через Wi-Fi, false в противном случае
*/
fun isWifiConnection(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
}
/**
* Проверка типа подключения (мобильная сеть)
* @param context Контекст приложения
* @return true, если подключение осуществляется через мобильную сеть, false в противном случае
*/
fun isMobileConnection(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
}
/**
* Типы подключения к интернету
*/
enum class ConnectionType {
WIFI, // Подключение через WiFi
CELLULAR, // Подключение через мобильную сеть
NONE // Отсутствие подключения
}
}

View File

@ -0,0 +1,81 @@
package com.example.rehabilitation.Feedback
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Setting.SettingFragment
import com.example.rehabilitation.databinding.FragmentFeedbackBinding
class FeedbackFragment : Fragment() {
private lateinit var binding: FragmentFeedbackBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentFeedbackBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if(isAdded()) {
//Выход
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.CLMain, SettingFragment.newInstance())
?.commit()
}
//Переход по ссылке на сайт
binding.txtUrlVmeda.setOnClickListener {
val i = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.vmeda.org/"))
startActivity(i)
}
//
// //Переход на почту
// binding.txtEmailDoctor.setOnClickListener{
// val intent = Intent(Intent.ACTION_SEND)
// intent.data = Uri.parse("mailto:")
// intent.type = "text/plain"
// intent.putExtra(Intent.EXTRA_EMAIL, arrayOf(binding.txtEmailDoctor.text.toString()))// herer adresses is already string
//
// try{
// startActivity(Intent.createChooser(intent,"Choose Email Client..."))
// }
// catch (e:Exception){
// Toast.makeText(this,e.message, Toast.LENGTH_LONG).show()
// }
// }
// //Номер врача
// binding.txtNumberDoctor.setOnClickListener{
// val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + binding.txtNumberDoctor.text.toString()))
// startActivity(intent)
// }
//Номер регистратуры
binding.txtNumberRegister.setOnClickListener {
val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + "+78122923286"))
startActivity(intent)
}
//Номер ДМС
binding.txtNumberDMS.setOnClickListener {
val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + "+78122923412"))
startActivity(intent)
}
}
}
companion object {
fun newInstance() = FeedbackFragment()
}
}

View File

@ -0,0 +1,142 @@
package com.example.rehabilitation
import android.content.SharedPreferences
import com.example.rehabilitation.Calendare.CalendareModel
import com.example.rehabilitation.Sport.Image.ImageSportModel
import com.example.rehabilitation.Progress.AfterListModel
import com.example.rehabilitation.Progress.BeforeListModel
import com.example.rehabilitation.Progress.ProgressModel
import java.io.File
import java.io.FileOutputStream
//Постоянное хранилище
var prefUserPatientToken: SharedPreferences? = null
var UserPatientToken:String = ""
var pref: SharedPreferences? = null
//Общее количество дней курса
var prefSportCursDayAll: SharedPreferences? = null
var SportCursDayAll :Int = 0
var prefSportCursDayLast: SharedPreferences? = null
var SportCursDayLast :String = ""
var prefSportCursNumber: SharedPreferences? = null
var prefCursDay: SharedPreferences? = null
var SportCursDay :Int = 0
//7 дней пройдено
var prefSport7Day: SharedPreferences? = null
var Sport7Day :Int = 0
//15 дней пройдено
var prefSport15Day: SharedPreferences? = null
var Sport15Day :Int = 0
//15 дней пройдено и отправлен отчет
var prefSport15DayAll: SharedPreferences? = null
var Sport15DayAll :Int = 0
var prefSportCursDayNumber: SharedPreferences? = null
var SportCursDayNumber :Int = 0
var prefSport: SharedPreferences? = null
var SportUserTrue = 0
var prefCursDangerDayBefore: SharedPreferences? = null
var SportCursDayDangerBefore:Int = 0
var prefCursDangerDayAfter: SharedPreferences? = null
var SportCursDayDangerAfter:Int = 0
var prefCursDayNull: SharedPreferences? = null
var CursDayNull:String = ""
var prefSportPlusCount: SharedPreferences? = null
var SportPlusCount:Int = 0
var prefSportMaxCount: SharedPreferences? = null
var SportMaxCount:Int = 0
var prefDayBefore: SharedPreferences? = null
var DayBefore:String = ""
var prefDayAfter: SharedPreferences? = null
var DayAfter:String = ""
var prefPauseDay: SharedPreferences? = null
var PauseDay:String = ""
var prefBlock: SharedPreferences? = null
var Block:String = ""
var prefFIO: SharedPreferences? = null
var FIO:String = ""
var prefEmailPatient: SharedPreferences? = null
var EmailPatient:String = ""
//Дата начала тренировки
var prefSportDateStart: SharedPreferences? = null
var SportDateStart:String = ""
var prefUser: SharedPreferences? = null
//Хранилище для анкеты
//var questionnaire: SharedPreferences? = null
var questionnaire_before :String = ""
var questionnaire_after:String = ""
var nameSport :String = ""
var countSport:Int? = null
var countSportPlus:String = ""
//Ключи для хранилишь
//Для пациента
var tokenClass:String = ""
var counter1:String = ""
//Для врача
var counter2:String = ""
var tokenClassDoctor:String = ""
var countCategory:String = ""
//Отчет по ребилитации
var listCheckSportDay:String = ""
//Доктор
var loginDoctor:String = "maxi05092003"
//Пациент
var loginPatient:String = "t.t.maxi05092003@gmail.com"
//Хранения отчета на время
var checkDaySportString:String = ""
//Хранения для перехода на страницу
var daySpoartOpen:Int = 0
var daySpoartOpenDate:String = ""
val daySpoartOpenKey:Int = 12321313
//var itemDayOpenDate:MonthModel
//Анкетирование
var listBefore:List<BeforeListModel> = listOf()
var listAfter:List<AfterListModel> = listOf()
//Прогрес
var listProgressAll:List<ProgressModel> = listOf()
var listProgressCheck:List<ProgressModel> = listOf()
var listImageSport:List<ImageSportModel> = listOf()
var uriFileEF: File? =null
var fileUri2: FileOutputStream? =null
//Переменная для хранения дня, чтобы при нажатие на главной тсранице или в календаре
var dateHomeCalendare:String = ""
class Hranilihe {
}

View File

@ -0,0 +1,50 @@
package com.example.rehabilitation.fragment.InfoFragment
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InformationFragment
import com.example.rehabilitation.databinding.FragmentCommonInfoBinding
class CommonInfoFragment : Fragment() {
private lateinit var binding: FragmentCommonInfoBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentCommonInfoBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InformationFragment.newInstance())?.addToBackStack(null)?.commit()
}
}
// override fun onResume() {
// super.onResume()
// binding.CLCommonInfo.visibility = View.VISIBLE
// }
//
// override fun onDestroy() {
// super.onDestroy()
// binding.CLCommonInfo.visibility = View.GONE
//
// }
companion object {
@JvmStatic
fun newInstance() = CommonInfoFragment()
}
}

View File

@ -0,0 +1,49 @@
package com.example.rehabilitation.fragment.InfoFragment
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InformationFragment
import com.example.rehabilitation.databinding.FragmentMedicalReabilitationBinding
class MedicalReabilitationFragment : Fragment() {
private lateinit var binding: FragmentMedicalReabilitationBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMedicalReabilitationBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InformationFragment.newInstance())?.addToBackStack(null)?.commit()
}
}
// override fun onResume() {
// super.onResume()
// binding.CLMadicalReabilitation.visibility = View.VISIBLE
// }
//
// override fun onDestroy() {
// super.onDestroy()
// binding.CLMadicalReabilitation.visibility = View.GONE
//
// }
companion object {
@JvmStatic
fun newInstance() = MedicalReabilitationFragment()
}
}

View File

@ -0,0 +1,48 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import android.transition.TransitionInflater
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R as R_P
import android.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentBreathingExercisesBinding
class BreathingExercisesFragment : Fragment() {
private lateinit var binding:FragmentBreathingExercisesBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentBreathingExercisesBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R_P.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
val inflater = TransitionInflater.from(requireContext())
binding.DecongestantTherapy.setOnClickListener {
exitTransition = inflater.inflateTransition(R.transition.slide_top)
activity?.supportFragmentManager?.beginTransaction()?.replace(R_P.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.DecongestantTherapyFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
//enterTransition = inflater.inflateTransition(R_P.transition.slide_bottom)
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.BreathingExercisesFragment()
}
}

View File

@ -0,0 +1,42 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentContourPreventionBinding
class ContourPreventionFragment : Fragment() {
private lateinit var binding:FragmentContourPreventionBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentContourPreventionBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnPhantomPains.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.PhantomPainsFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.ContourPreventionFragment()
}
}

View File

@ -0,0 +1,41 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentDecongestantTherapyBinding
class DecongestantTherapyFragment : Fragment() {
private lateinit var binding: FragmentDecongestantTherapyBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentDecongestantTherapyBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnContracturesPrevention.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.ContourPreventionFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.DecongestantTherapyFragment()
}
}

View File

@ -0,0 +1,42 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentFormationOfTheStumpBinding
class FormationOfTheStumpFragment : Fragment() {
private lateinit var binding:FragmentFormationOfTheStumpBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentFormationOfTheStumpBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnPhysicalExercises.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.PhysicalExercisesFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.FormationOfTheStumpFragment()
}
}

View File

@ -0,0 +1,44 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import android.transition.TransitionInflater
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentMotorModeBinding
class MotorModeFragment : Fragment() {
private lateinit var binding: FragmentMotorModeBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMotorModeBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
// val inflater = TransitionInflater.from(requireContext())
// exitTransition = inflater.inflateTransition(R.transition.slide_bottom)
binding.btnStumpCare.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.StumpCareFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.MotorModeFragment()
}
}

View File

@ -0,0 +1,41 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentOrganizationOfTheDailyRoutineAfterSurgeryBinding
class OrganizationOfTheDailyRoutineAfterSurgeryFragment : Fragment() {
private lateinit var binding: FragmentOrganizationOfTheDailyRoutineAfterSurgeryBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentOrganizationOfTheDailyRoutineAfterSurgeryBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnOrganizationOfTheDayRegimeOfTheSecondWeekAfterAmputation.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.OrganizationOfTheDayRegimeOfTheSecondWeekAfterAmputationFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.OrganizationOfTheDailyRoutineAfterSurgeryFragment()
}
}

View File

@ -0,0 +1,36 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentOrganizationOfTheDayRegimeOfTheSecondWeekAfterAmputationBinding
class OrganizationOfTheDayRegimeOfTheSecondWeekAfterAmputationFragment : Fragment() {
private lateinit var binding: FragmentOrganizationOfTheDayRegimeOfTheSecondWeekAfterAmputationBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentOrganizationOfTheDayRegimeOfTheSecondWeekAfterAmputationBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.OrganizationOfTheDayRegimeOfTheSecondWeekAfterAmputationFragment()
}
}

View File

@ -0,0 +1,41 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentPhantomPainsBinding
class PhantomPainsFragment : Fragment() {
private lateinit var binding:FragmentPhantomPainsBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentPhantomPainsBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnSurfaceSensitivity.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.SurfaceSensitivityFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.PhantomPainsFragment()
}
}

View File

@ -0,0 +1,41 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentPhysicalExercisesBinding
class PhysicalExercisesFragment : Fragment() {
private lateinit var binding: FragmentPhysicalExercisesBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentPhysicalExercisesBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnOrganizationOfTheDailyRoutineAfterSurgery.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.OrganizationOfTheDailyRoutineAfterSurgeryFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.PhysicalExercisesFragment()
}
}

View File

@ -0,0 +1,43 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentStumpCareBinding
class StumpCareFragment : Fragment() {
private lateinit var binding: FragmentStumpCareBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentStumpCareBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnBreathingExercises.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.BreathingExercisesFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.StumpCareFragment()
}
}

View File

@ -0,0 +1,42 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentSurfaceSensitivityBinding
class SurfaceSensitivityFragment : Fragment() {
private lateinit var binding:FragmentSurfaceSensitivityBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentSurfaceSensitivityBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnFormationOfTheStump.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.FormationOfTheStumpFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.SurfaceSensitivityFragment()
}
}

View File

@ -0,0 +1,111 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.BreathingExercisesFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.ContourPreventionFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.DecongestantTherapyFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.FormationOfTheStumpFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.MotorModeFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.OrganizationOfTheDailyRoutineAfterSurgeryFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.OrganizationOfTheDayRegimeOfTheSecondWeekAfterAmputationFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.PhantomPainsFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.PhysicalExercisesFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.StumpCareFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.SurfaceSensitivityFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendationsFragment
import com.example.rehabilitation.databinding.FragmentEarlyPostoperativePeriodBinding
class EarlyPostoperativePeriodFragment : Fragment() {
private lateinit var binding:FragmentEarlyPostoperativePeriodBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentEarlyPostoperativePeriodBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnMotorMode.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.MotorModeFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnStumpCare.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.StumpCareFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnBreathingExercises.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.BreathingExercisesFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.DecongestantTherapy.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.DecongestantTherapyFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnContracturesPrevention.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.ContourPreventionFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnPhantomPains.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.PhantomPainsFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendationsFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnFurther.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
binding.btnSurfaceSensitivity.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.SurfaceSensitivityFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnFormationOfTheStump.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.FormationOfTheStumpFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnPhysicalExercises.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.PhysicalExercisesFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnOrganizationOfTheDailyRoutineAfterSurgery.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.OrganizationOfTheDailyRoutineAfterSurgeryFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnOrganizationOfTheDayRegimeOfTheSecondWeekAfterAmputation.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriod.OrganizationOfTheDayRegimeOfTheSecondWeekAfterAmputationFragment.newInstance())?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment()
}
}

View File

@ -0,0 +1,43 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentDecongestantTherapyLateBinding
class DecongestantTherapyLateFragment : Fragment() {
private lateinit var binding: FragmentDecongestantTherapyLateBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentDecongestantTherapyLateBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(
R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnMassageTechniqueLate.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.MassageTechniqueLateFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.DecongestantTherapyLateFragment()
}
}

View File

@ -0,0 +1,42 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentMassageTechniqueLateBinding
class MassageTechniqueLateFragment : Fragment() {
private lateinit var binding: FragmentMassageTechniqueLateBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMassageTechniqueLateBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnPreventionOfContracturesLate.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PreventionOfContracturesLateFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.MassageTechniqueLateFragment()
}
}

View File

@ -0,0 +1,38 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentPhantomPainsLateBinding
class PhantomPainsLateFragment : Fragment() {
private lateinit var binding:FragmentPhantomPainsLateBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentPhantomPainsLateBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(
R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PhantomPainsLateFragment()
}
}

View File

@ -0,0 +1,43 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentPreparationForProstheticsLateBinding
class PreparationForProstheticsLateFragment : Fragment() {
private lateinit var binding: FragmentPreparationForProstheticsLateBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentPreparationForProstheticsLateBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(
R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnDecongestantTherapyLate.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.DecongestantTherapyLateFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PreparationForProstheticsLateFragment()
}
}

View File

@ -0,0 +1,41 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment
import com.example.rehabilitation.databinding.FragmentPreventionOfContracturesLateBinding
class PreventionOfContracturesLateFragment : Fragment() {
private lateinit var binding: FragmentPreventionOfContracturesLateBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentPreventionOfContracturesLateBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnPhantomPainsLate.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PhantomPainsLateFragment.Companion.newInstance()
)?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PreventionOfContracturesLateFragment()
}
}

View File

@ -0,0 +1,63 @@
package com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.DecongestantTherapyLateFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.MassageTechniqueLateFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PhantomPainsLateFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PreparationForProstheticsLateFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PreventionOfContracturesLateFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendationsFragment
import com.example.rehabilitation.databinding.FragmentLatePostoperativePeriodBinding
class LatePostoperativePeriodFragment : Fragment() {
private lateinit var binding: FragmentLatePostoperativePeriodBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentLatePostoperativePeriodBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendationsFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnPreparationForProstheticsLate.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PreparationForProstheticsLateFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnDecongestantTherapyLate.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.DecongestantTherapyLateFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnMassageTechniqueLate.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.MassageTechniqueLateFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnPreventionOfContracturesLate.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PreventionOfContracturesLateFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnPhantomPainsLate.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriod.PhantomPainsLateFragment.newInstance())?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment()
}
}

View File

@ -0,0 +1,48 @@
package com.example.rehabilitation.Information.InfoFragment
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment
import com.example.rehabilitation.Information.InformationFragment
import com.example.rehabilitation.databinding.FragmentMethodologicalRecommendationsBinding
class MethodologicalRecommendationsFragment : Fragment() {
private lateinit var binding: FragmentMethodologicalRecommendationsBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMethodologicalRecommendationsBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InformationFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnEarlyPostoperativePeriod.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.EarlyPostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
binding.btnLatePostoperativePeriod.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendations.LatePostoperativePeriodFragment.newInstance())?.addToBackStack(null)?.commit()
}
}
companion object {
fun newInstance() =
com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendationsFragment()
}
}

View File

@ -0,0 +1,50 @@
package com.example.rehabilitation.fragment.InfoFragment
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InformationFragment
import com.example.rehabilitation.databinding.FragmentFaqBinding
class faqFragment : Fragment() {
private lateinit var binding: FragmentFaqBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = FragmentFaqBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnExit.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.CLInformationMain,
com.example.rehabilitation.Information.InformationFragment.newInstance())?.addToBackStack(null)?.commit()
}
}
// override fun onResume() {
// super.onResume()
// binding.CLFaq.visibility = View.VISIBLE
// }
//
// override fun onDestroy() {
// super.onDestroy()
// binding.CLFaq.visibility = View.GONE
//
// }
companion object {
@JvmStatic
fun newInstance() = faqFragment()
}
}

View File

@ -0,0 +1,118 @@
package com.example.rehabilitation.Information
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.MainActivity
import com.example.rehabilitation.R
import com.example.rehabilitation.Information.InfoFragment.MethodologicalRecommendationsFragment
import com.example.rehabilitation.MainFragment
import com.example.rehabilitation.Setting.SettingFragment
import com.example.rehabilitation.databinding.FragmentInformationBinding
import com.example.rehabilitation.fragment.InfoFragment.CommonInfoFragment
import com.example.rehabilitation.fragment.InfoFragment.MedicalReabilitationFragment
import com.example.rehabilitation.fragment.InfoFragment.faqFragment
class InformationFragment : Fragment() {
private lateinit var binding: FragmentInformationBinding
//Класс проверки интеренета
val enternetCheck = EnternetCheck()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentInformationBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if(isAdded()) {
//Выход со страницы
binding.btnExitInformation.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.CLMain, MainFragment.newInstance())
?.commit()
}
binding.methodologicalRecommendationsButton.setOnClickListener {
// val infoFrag = activity?.supportFragmentManager?.beginTransaction()
// infoFrag?.replace(
// R.id.CLInformation,MethodologicalRecommendationsFragment.newInstance()
// )
// infoFrag?.addToBackStack(null)
// infoFrag?.commit()
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.CLInformationMain, MethodologicalRecommendationsFragment.newInstance())
?.commit()
}
binding.commonInformationButton.setOnClickListener {
// val infoFrag = activity?.supportFragmentManager?.beginTransaction()
// infoFrag?.replace(R.id.CLInformation, CommonInfoFragment.newInstance())
// infoFrag?.addToBackStack(null)
// infoFrag?.commit()
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.CLInformationMain, CommonInfoFragment.newInstance())
?.commit()
}
binding.frequentlyAskedQuestionsButton.setOnClickListener {
// val infoFrag = activity?.supportFragmentManager?.beginTransaction()
// infoFrag?.replace(R.id.CLInformation, faqFragment.newInstance())
// infoFrag?.addToBackStack(null)
// infoFrag?.commit()
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.CLInformationMain, faqFragment.newInstance())
?.commit()
}
binding.medicalReabilitationButton.setOnClickListener {
// val infoFrag = activity?.supportFragmentManager?.beginTransaction()
// infoFrag?.replace(R.id.CLInformation, MedicalReabilitationFragment.newInstance())
// infoFrag?.addToBackStack(null)
// infoFrag?.commit()
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.CLInformationMain, MedicalReabilitationFragment.newInstance())
?.commit()
}
binding.fondButton.setOnClickListener {
val i = Intent(
Intent.ACTION_VIEW,
Uri.parse("https://фонд-защитники-отечества.рф/filials")
)
startActivity(i)
}
}
}
// override fun onDestroy() {
// super.onDestroy()
// activity?.finish()
//
// binding.CLFragmentInformation.visibility = View.GONE
// }
//
// override fun onResume() {
// super.onResume()
// binding.CLFragmentInformation.visibility = View.VISIBLE
//
// }
companion object {
fun newInstance() = com.example.rehabilitation.Information.InformationFragment()
}
}

View File

@ -0,0 +1,33 @@
package com.example.rehabilitation.Information
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R
import com.example.rehabilitation.databinding.FragmentInformationMainBinding
class InformationMainFragment : Fragment() {
private lateinit var binding: FragmentInformationMainBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentInformationMainBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.CLInformationMain, InformationFragment.newInstance())
?.commit()
}
companion object {
fun newInstance() = InformationMainFragment()
}
}

View File

@ -0,0 +1,190 @@
package com.example.rehabilitation
import android.annotation.SuppressLint
import android.view.WindowManager
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import com.example.rehabilitation.Auth.AuthFragment
import com.example.rehabilitation.Auth.AuthorizationActivity
import com.example.rehabilitation.CodeError.Code429Activity
import com.example.rehabilitation.CodeError.Code500Activity
import com.example.rehabilitation.Enternet.EnternetActivity
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.Retrofit.PatientApi
import com.example.rehabilitation.databinding.ActivityMainBinding
import com.example.sqlitework.dip.MainViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
/**
* Главная активность приложения
* Отвечает за инициализацию приложения и управление основным потоком
*/
class MainActivity : AppCompatActivity() {
// Привязка к layout файлу
private lateinit var binding: ActivityMainBinding
// API для работы с данными пациента
private lateinit var patientApi: PatientApi
// ViewModel для работы с данными пациента
private val modelPatient: PatientViewModel by viewModels()
// ViewModel для работы с основными данными
private val model: MainViewModel by viewModels()
// Токен авторизации
private var Token = ""
// Класс для работы с настройками
val prefPatientConclusion = ConclusionPref()
// Время последнего нажатия кнопки "назад"
var backPressedTime: Long = 0
// Класс для проверки интернет-соединения
val enternetCheck = EnternetCheck()
@SuppressLint("DiscouragedApi")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Установка флага безопасности для предотвращения скриншотов
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
MainAndAuth()
}
/**
* Проверяет наличие токена и инициализирует соответствующий экран
*/
fun MainAndAuth() {
Token = prefPatientConclusion.conclusionToken(this)
Log.i("sadasdsadsd", Token)
if (Token == "") {
Auth()
} else {
CheckTokenAuth(Token)
}
}
/**
* Показывает экран авторизации
*/
fun Auth() {
binding.CLLoad.visibility = View.GONE
// Замена текущего фрагмента на экран авторизации
supportFragmentManager.beginTransaction()
.replace(R.id.CLMain, AuthFragment.newInstance())
.commit()
}
/**
* Инициализирует главный экран приложения
*/
fun Main() {
binding.CLLoad.visibility = View.GONE
fragment_inicializ()
}
/**
* Проверяет валидность токена авторизации
* @param token Токен для проверки
*/
@SuppressLint("SuspiciousIndentation")
private fun CheckTokenAuth(token: String) {
if (enternetCheck.isOnline(this)) {
initRetrofit()
CoroutineScope(Dispatchers.IO).launch {
val response = patientApi.CheckToken("Bearer $token")
runOnUiThread {
// Обработка ответа от сервера
val List = response.body()
val Nice = response.isSuccessful
val Code = response.code()
// Обработка различных кодов ответа
when (Code) {
429 -> {
// Слишком много запросов
val intetn = Intent(this@MainActivity, Code429Activity::class.java)
startActivity(intetn)
}
200 -> {
// Успешный ответ
if (Nice) {
Main()
} else {
Auth()
}
}
500 -> {
// Ошибка сервера
val intetn = Intent(this@MainActivity, Code500Activity::class.java)
startActivity(intetn)
}
401 -> {
// Неавторизованный доступ
val intetn = Intent(this@MainActivity, AuthorizationActivity::class.java)
finish()
startActivity(intetn)
}
}
}
}
} else {
// Нет интернет-соединения
val intetn = Intent(this, Code500Activity::class.java)
finish()
startActivity(intetn)
}
}
/**
* Инициализирует Retrofit для работы с API
*/
private fun initRetrofit() {
// Настройка логирования
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
// Создание HTTP клиента
val client = OkHttpClient
.Builder()
.addInterceptor(interceptor)
.build()
// Инициализация Retrofit
val retrofit = Retrofit.Builder()
.baseUrl("https://rehabilitation.vmeda.org/api/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
patientApi = retrofit.create(PatientApi::class.java)
}
/**
* Инициализирует главный фрагмент
*/
private fun fragment_inicializ() {
supportFragmentManager.beginTransaction()
.replace(R.id.CLMain, MainFragment.newInstance())
.commit()
}
override fun onDestroy() {
super.onDestroy()
finish()
}
override fun onResume() {
super.onResume()
}
}

View File

@ -0,0 +1,482 @@
package com.example.rehabilitation
import android.annotation.SuppressLint
import android.content.Intent
import android.icu.text.SimpleDateFormat
import android.icu.util.Calendar
import android.os.Bundle
import android.os.SystemClock
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import com.example.admin.Toast.showCustomInfoToast
import com.example.rehabilitation.Appeals.AppealsFragment
import com.example.rehabilitation.Auth.AuthorizationActivity
import com.example.rehabilitation.Calendare.CalendarFragment
import com.example.rehabilitation.CodeError.Code429Activity
import com.example.rehabilitation.CodeError.Code500Activity
import com.example.rehabilitation.Enternet.EnternetActivity
import com.example.rehabilitation.Enternet.EnternetCheck
import com.example.rehabilitation.Information.InformationFragment
import com.example.rehabilitation.Information.InformationMainFragment
import com.example.rehabilitation.Pref.ConclusionPref
import com.example.rehabilitation.Progress.ProgresFragment
import com.example.rehabilitation.Retrofit.PatientApi
import com.example.rehabilitation.Setting.SettingFragment
import com.example.rehabilitation.Sport.DayAdapter
import com.example.rehabilitation.Sport.SceduleFragment
import com.example.rehabilitation.Sport.SportForDayModel
import com.example.rehabilitation.databinding.FragmentMainBinding
import com.example.rehabilitation.model_adapter.DataModel
import com.example.sqlitework.dip.MainViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.Date
import java.util.Timer
import kotlin.concurrent.fixedRateTimer
/**
* Основной фрагмент приложения
* Отвечает за отображение главного экрана и навигацию между разделами
*/
class MainFragment : Fragment() {
// ViewBinding для доступа к элементам интерфейса
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
// ViewModel для передачи данных между фрагментами
private val dataModel: DataModel by viewModels()
// ViewModel для работы с основными данными
private val model: MainViewModel by activityViewModels()
// ViewModel для работы с данными пациента
private val modelPatient: PatientViewModel by activityViewModels()
// API для работы с данными пациента
private lateinit var patientApi: PatientApi
// Таймер для обновления данных
private lateinit var timer: Timer
// Класс для работы с настройками
val prefPatientConclusion = ConclusionPref()
// Класс для проверки интернет-соединения
val enternetCheck = EnternetCheck()
// Форматтер для даты
@SuppressLint("SimpleDateFormat")
var sdf: SimpleDateFormat = SimpleDateFormat("EEEE")
var d: Date = Date()
var dayOfTheWeek: String = sdf.format(d)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentMainBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Инициализация ViewModel
viewModel = ViewModelProvider(this)[PatientViewModel::class.java]
// Настройка обработчиков нажатий на кнопки
setupClickListeners()
// Наблюдение за изменениями данных
observeViewModel()
checkForUpdates()
if (isAdded) {
main_inicializ()
}
// Наблюдение за изменениями в меню
dataModel.fragmentMenu.observe(viewLifecycleOwner, Observer {
binding.buttonNavigation.selectedItemId = it
})
}
/**
* Настройка обработчиков нажатий на кнопки
*/
private fun setupClickListeners() {
// Переход к разделу анкет
binding.btnQuestionnaires.setOnClickListener {
findNavController().navigate(R.id.action_mainFragment_to_questionnaireFragment)
}
// Переход к разделу расписания
binding.btnSchedule.setOnClickListener {
findNavController().navigate(R.id.action_mainFragment_to_sceduleFragment)
}
// Переход к разделу обращений
binding.btnAppeals.setOnClickListener {
findNavController().navigate(R.id.action_mainFragment_to_appealsFragment)
}
// Переход к разделу профиля
binding.btnProfile.setOnClickListener {
findNavController().navigate(R.id.action_mainFragment_to_profileFragment)
}
}
/**
* Наблюдение за изменениями данных в ViewModel
*/
private fun observeViewModel() {
// Наблюдение за статусом загрузки
viewModel.isLoading.observe(viewLifecycleOwner) { isLoading ->
binding.progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
}
// Наблюдение за ошибками
viewModel.error.observe(viewLifecycleOwner) { error ->
error?.let {
// Отображение ошибки пользователю
showError(it)
}
}
}
/**
* Отображение ошибки пользователю
* @param message Сообщение об ошибке
*/
private fun showError(message: String) {
// TODO: Реализовать отображение ошибки
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
/**
* Инициализация главного экрана
*/
fun main_inicializ() {
// Наблюдение за изменениями в меню
dataModel.fragmentMenu.observe(this as LifecycleOwner, {
binding.buttonNavigation.selectedItemId = it
})
// Инициализация фрагментов
fragment_inicializ()
// Обработчик нажатия на кнопку настроек
binding.btnSetting.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.CLMain, SettingFragment.newInstance())
?.commit()
}
// Обработчик нажатия на кнопку информации
binding.btnInformation.setOnClickListener {
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.CLMain, InformationMainFragment.newInstance())
?.commit()
}
// Отображение текущей даты
addDate()
}
/**
* Инициализация навигации между фрагментами
*/
fun fragment_inicializ() {
// Установка начального фрагмента (расписание)
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.placeHolderFragment, SceduleFragment.newInstance())
?.commit()
// Установка выбранного элемента в нижней навигации
binding.buttonNavigation.selectedItemId = R.id.schedule
// Обработчик выбора элемента в нижней навигации
binding.buttonNavigation.setOnItemSelectedListener {
when (it.itemId) {
R.id.schedule -> {
// Переход к расписанию
if (!isClickRecently()) {
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.placeHolderFragment, SceduleFragment.newInstance())
?.commit()
}
}
R.id.calendar -> {
// Переход к календарю
val view = prefPatientConclusion.conclusionView(requireContext())
if(view.toInt()==1 || view.toInt()==2){
Toast(requireContext()).showCustomInfoToast("У вас отсутсвует курс", requireActivity())
} else {
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.placeHolderFragment, CalendarFragment.newInstance())
?.commit()
}
}
R.id.progress -> {
// Переход к прогрессу
val view = prefPatientConclusion.conclusionView(requireContext())
if(view.toInt()==1 || view.toInt()==2){
Toast(requireContext()).showCustomInfoToast("У вас отсутсвует курс", requireActivity())
} else {
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.placeHolderFragment, ProgresFragment.newInstance())
?.commit()
}
}
R.id.chat -> {
// Переход к чату
if (!isClickRecently()) {
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.placeHolderFragment, AppealsFragment.newInstance())
?.commit()
}
}
}
true
}
}
/**
* Добавление текущей даты на экран
*/
private fun addDate() {
val calendar: Calendar = Calendar.getInstance()
val sdf: SimpleDateFormat = SimpleDateFormat("EEEE")
val d: Date = Date()
val DayOfTheWeek: String = sdf.format(d)
val Day = calendar.get(Calendar.DATE)
val Month = calendar.get(Calendar.MONTH).plus(1)
var day = Day.toString()
var month = ""
var date_of_the_week = ""
// Преобразование номера месяца в название
month = when (Month) {
1 -> "Январь"
2 -> "Февраль"
3 -> "Март"
4 -> "Апрель"
5 -> "Май"
6 -> "Июнь"
7 -> "Июль"
8 -> "Август"
9 -> "Сентябрь"
10 -> "Октябрь"
11 -> "Ноябрь"
12 -> "Декабрь"
else -> ""
}
// Преобразование дня недели в сокращенное название
date_of_the_week = when (dayOfTheWeek) {
"Monday" -> "Пн"
"Tuesday" -> "Вт"
"Wednesday" -> "Ср"
"Thursday" -> "Чт"
"Friday" -> "Пт"
"Saturday" -> "Сб"
"Sunday" -> "Вс"
"Понедельник" -> "Пн"
"Вторник" -> "Вт"
"Стреда" -> "Ср"
"Четверг" -> "Чт"
"Пятница" -> "Пт"
"Суббота" -> "Сб"
"Воскресенье" -> "Вс"
else -> ""
}
// Установка даты в TextView
binding.tvDate.text = "$date_of_the_week, $day $month"
}
/**
* Проверка частоты нажатий для предотвращения множественных нажатий
*/
private fun isClickRecently(): Boolean {
if (SystemClock.elapsedRealtime() - lastClickTime < 1000) {
return true
}
lastClickTime = SystemClock.elapsedRealtime()
return false
}
companion object {
private var lastClickTime: Long = 0
}
//Получения экрана
fun GetVisibleViewListTimer() {
if (enternetCheck.isOnline(requireContext())) {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val listProduct = patientApi.VisibleView3("Bearer $Tokens")
activity?.runOnUiThread {
//Фиксируем полученные данные
val List = listProduct.body()
val Nice = listProduct.isSuccessful
val Code = listProduct.code()
if(Code==429){
val intetn = Intent(requireContext(), Code429Activity::class.java)
startActivity(intetn)
}
else if(Code==200) {
//Если нету ошибок
if (Nice) {
//Если нету ошибок
if (List != null) {
modelPatient.viewCurrent.value = List
}
}
//Следующий по счету
GetSportDay()
}
else if (Code == 500) {
val intetn = Intent(requireContext(), Code500Activity::class.java)
startActivity(intetn)
}
}
}
} else {
val intetn = Intent(requireContext(), EnternetActivity::class.java)
activity?.finish()
startActivity(intetn)
}
}
val dayAdapter = DayAdapter(object : DayAdapter.Listener {
override fun onClickSport(item: SportForDayModel) {
// Обработка нажатия на элемент
Log.d("Sport", "Clicked: ${item.number}")
}
})
//Получения списка упражнений
fun GetSportDay() {
if (enternetCheck.isOnline(requireContext())) {
initRetrofit()
val Tokens = prefPatientConclusion.conclusionToken(requireContext())
CoroutineScope(Dispatchers.IO).launch {
val sportDay = patientApi.GetSportDay("Bearer $Tokens")
requireActivity().runOnUiThread {
val listResponse = sportDay.body()
val isSuccess = sportDay.isSuccessful
val responseCode = sportDay.code()
if (responseCode == 429) {
val intent = Intent(requireContext(), Code429Activity::class.java)
startActivity(intent)
} else if (responseCode == 200) {
if (isSuccess && listResponse != null) {
// Допустим, что упражнение имеет свойство "id" и оно правильно отсортировано
// Мы сортируем упражнения по их идентификатору, чтобы они шли по порядку
val sortedList = listResponse.sport_for_day.sortedBy { it.number.toString() }
model.liveDayList.value = sortedList
}
} else if (responseCode == 500) {
val intent = Intent(requireContext(), Code500Activity::class.java)
startActivity(intent)
}
}
}
} else {
val intent = Intent(requireContext(), EnternetActivity::class.java)
activity?.finish()
startActivity(intent)
}
}
// fun ProgressPatientCourses() {
// if (enternetCheck.isOnline(requireContext())) {
// initRetrofit()
// val Tokens = prefPatientConclusion.conclusionToken(requireContext())
// CoroutineScope(Dispatchers.IO).launch {
// val progress = patientApi.ProgressPatientCourses("Bearer $Tokens")
//
// activity?.runOnUiThread {
//
// //Фиксируем полученные данные
// val progressMes = progress.body()
// val progressMesCode = progress.isSuccessful()
// //Если нету ошибок
// if (progressMesCode) {
// model.liveProgressCheckList.value = progressMes?.search_check_sport
// }
// }
// }
// } else {
// val intetn = Intent(requireContext(), EnternetActivity::class.java)
// activity?.finish()
// startActivity(intetn)
// }
//
// }
//Инициализация подлючения к серверу
private fun initRetrofit() {
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient
.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://rehabilitation.vmeda.org/api/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
patientApi = retrofit.create(PatientApi::class.java)
}
override fun onResume() {
super.onResume()
checkForUpdates()
}
override fun onPause() {
super.onPause()
if (::timer.isInitialized) { // Clean up the Timer
timer.cancel()
timer.purge()
}
}
private fun checkForUpdates() {
viewLifecycleOwner.lifecycleScope.launch {
while (viewLifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
GetVisibleViewListTimer()
delay(15000) // 15 seconds delay
}
}
}
}

View File

@ -0,0 +1,27 @@
package com.example.rehabilitation.Message
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.rehabilitation.R as R_P
import android.R
import com.example.rehabilitation.databinding.FragmentMessageChatBinding
class MessageChatFragment : Fragment() {
private lateinit var binding:FragmentMessageChatBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMessageChatBinding.inflate(layoutInflater,container,false)
return binding.root
}
companion object {
fun newInstance() = MessageChatFragment()
}
}

View File

@ -0,0 +1,6 @@
package com.example.rehabilitation
data class MessageModel(
val message: String,
)

View File

@ -0,0 +1,115 @@
package com.example.rehabilitation.Model
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.*
/**
* Интерфейс для взаимодействия с API
* Определяет все доступные эндпоинты и методы для работы с данными
*/
interface ApiService {
/**
* Получение списка анкет для пациента
* @param patientId ID пациента
* @return Список анкет
*/
@GET("questionnaires")
suspend fun getQuestionnaires(@Query("patientId") patientId: Int): Response<List<Questionnaire>>
/**
* Сохранение новой анкеты
* @param questionnaire Данные анкеты для сохранения
* @return Сохраненная анкета
*/
@POST("questionnaires")
suspend fun saveQuestionnaire(@Body questionnaire: QuestionnaireRequest): Response<Questionnaire>
/**
* Обновление существующей анкеты
* @param id ID анкеты
* @param questionnaire Данные анкеты для обновления
* @return Обновленная анкета
*/
@PUT("questionnaires/{id}")
suspend fun updateQuestionnaire(
@Path("id") id: Int,
@Body questionnaire: QuestionnaireRequest
): Response<Questionnaire>
/**
* Удаление анкеты
* @param id ID анкеты
* @return Пустой ответ при успешном удалении
*/
@DELETE("questionnaires/{id}")
suspend fun deleteQuestionnaire(@Path("id") id: Int): Response<Unit>
/**
* Получение анкеты по ID
* @param id ID анкеты
* @return Анкета
*/
@GET("questionnaires/{id}")
suspend fun getQuestionnaire(@Path("id") id: Int): Response<Questionnaire>
/**
* Получение списка расписаний для пациента
* @param patientId ID пациента
* @return Список расписаний
*/
@GET("schedules")
suspend fun getSchedules(@Query("patientId") patientId: Int): Response<List<Schedule>>
/**
* Сохранение нового расписания
* @param schedule Данные расписания для сохранения
* @return Сохраненное расписание
*/
@POST("schedules")
suspend fun saveSchedule(@Body schedule: ScheduleRequest): Response<Schedule>
/**
* Обновление существующего расписания
* @param id ID расписания
* @param schedule Данные расписания для обновления
* @return Обновленное расписание
*/
@PUT("schedules/{id}")
suspend fun updateSchedule(
@Path("id") id: Int,
@Body schedule: ScheduleRequest
): Response<Schedule>
/**
* Удаление расписания
* @param id ID расписания
* @return Пустой ответ при успешном удалении
*/
@DELETE("schedules/{id}")
suspend fun deleteSchedule(@Path("id") id: Int): Response<Unit>
/**
* Получение расписания по ID
* @param id ID расписания
* @return Расписание
*/
@GET("schedules/{id}")
suspend fun getSchedule(@Path("id") id: Int): Response<Schedule>
companion object {
/**
* Создание экземпляра ApiService
* @param baseUrl Базовый URL API
* @return Экземпляр ApiService
*/
fun create(baseUrl: String = "https://api.example.com/"): ApiService {
return Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
}
}

View File

@ -0,0 +1,68 @@
package com.example.rehabilitation.Model
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import com.example.rehabilitation.databinding.ActivityCode429Binding
/**
* Активность, отображаемая при получении ошибки 429 (Too Many Requests)
* Информирует пользователя о превышении лимита запросов и предлагает повторить попытку позже
*/
class Code429Activity : AppCompatActivity() {
// ViewBinding для безопасного доступа к UI элементам
private lateinit var binding: ActivityCode429Binding
// Обработчик для обновления UI
private val handler = Handler(Looper.getMainLooper())
// Задержка между проверками (в миллисекундах)
private val CHECK_DELAY = 5000L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCode429Binding.inflate(layoutInflater)
setContentView(binding.root)
// Настройка обработчиков нажатий
setupClickListeners()
// Запуск периодической проверки
startRetryCheck()
}
/**
* Настройка обработчиков нажатий на кнопки
*/
private fun setupClickListeners() {
// Обработчик нажатия на кнопку "Повторить"
binding.retryButton.setOnClickListener {
finish()
}
// Обработчик нажатия на кнопку "Выход"
binding.exitButton.setOnClickListener {
finish()
}
}
/**
* Запуск периодической проверки возможности повторного запроса
*/
private fun startRetryCheck() {
handler.postDelayed(object : Runnable {
override fun run() {
// По истечении задержки возвращаемся к предыдущей активности
finish()
handler.postDelayed(this, CHECK_DELAY)
}
}, CHECK_DELAY)
}
override fun onDestroy() {
super.onDestroy()
// Останавливаем периодическую проверку при уничтожении активности
handler.removeCallbacksAndMessages(null)
}
}

View File

@ -0,0 +1,68 @@
package com.example.rehabilitation.Model
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import com.example.rehabilitation.databinding.ActivityCode500Binding
/**
* Активность, отображаемая при получении ошибки 500 (Internal Server Error)
* Информирует пользователя о внутренней ошибке сервера и предлагает повторить попытку позже
*/
class Code500Activity : AppCompatActivity() {
// ViewBinding для безопасного доступа к UI элементам
private lateinit var binding: ActivityCode500Binding
// Обработчик для обновления UI
private val handler = Handler(Looper.getMainLooper())
// Задержка между проверками (в миллисекундах)
private val CHECK_DELAY = 5000L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCode500Binding.inflate(layoutInflater)
setContentView(binding.root)
// Настройка обработчиков нажатий
setupClickListeners()
// Запуск периодической проверки
startRetryCheck()
}
/**
* Настройка обработчиков нажатий на кнопки
*/
private fun setupClickListeners() {
// Обработчик нажатия на кнопку "Повторить"
binding.retryButton.setOnClickListener {
finish()
}
// Обработчик нажатия на кнопку "Выход"
binding.exitButton.setOnClickListener {
finish()
}
}
/**
* Запуск периодической проверки доступности сервера
*/
private fun startRetryCheck() {
handler.postDelayed(object : Runnable {
override fun run() {
// По истечении задержки возвращаемся к предыдущей активности
finish()
handler.postDelayed(this, CHECK_DELAY)
}
}, CHECK_DELAY)
}
override fun onDestroy() {
super.onDestroy()
// Останавливаем периодическую проверку при уничтожении активности
handler.removeCallbacksAndMessages(null)
}
}

View File

@ -0,0 +1,95 @@
package com.example.rehabilitation.Model
import android.content.Context
import android.content.SharedPreferences
/**
* Класс для работы с настройками приложения
* Обеспечивает сохранение и получение данных через SharedPreferences
*/
class ConclusionPref(context: Context) {
// Имя файла настроек
companion object {
private const val PREFS_NAME = "rehabilitation_prefs"
// Ключи для хранения данных
private const val KEY_PATIENT_ID = "patient_id"
private const val KEY_API_URL = "api_url"
private const val KEY_TOKEN = "token"
private const val KEY_IS_LOGGED_IN = "is_logged_in"
}
// Экземпляр SharedPreferences для доступа к настройкам
private val prefs: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
/**
* Сохранение ID пациента
* @param patientId ID пациента
*/
fun savePatientId(patientId: Int) {
prefs.edit().putInt(KEY_PATIENT_ID, patientId).apply()
}
/**
* Получение ID пациента
* @return ID пациента или -1, если не сохранен
*/
fun getPatientId(): Int {
return prefs.getInt(KEY_PATIENT_ID, -1)
}
/**
* Сохранение URL API
* @param apiUrl URL API
*/
fun saveApiUrl(apiUrl: String) {
prefs.edit().putString(KEY_API_URL, apiUrl).apply()
}
/**
* Получение URL API
* @return URL API или пустую строку, если не сохранен
*/
fun getApiUrl(): String {
return prefs.getString(KEY_API_URL, "") ?: ""
}
/**
* Сохранение токена авторизации
* @param token Токен авторизации
*/
fun saveToken(token: String) {
prefs.edit().putString(KEY_TOKEN, token).apply()
}
/**
* Получение токена авторизации
* @return Токен авторизации или пустую строку, если не сохранен
*/
fun getToken(): String {
return prefs.getString(KEY_TOKEN, "") ?: ""
}
/**
* Сохранение статуса авторизации
* @param isLoggedIn Статус авторизации
*/
fun saveLoginStatus(isLoggedIn: Boolean) {
prefs.edit().putBoolean(KEY_IS_LOGGED_IN, isLoggedIn).apply()
}
/**
* Проверка статуса авторизации
* @return true если пользователь авторизован, false в противном случае
*/
fun isLoggedIn(): Boolean {
return prefs.getBoolean(KEY_IS_LOGGED_IN, false)
}
/**
* Очистка всех сохраненных данных
*/
fun clearAll() {
prefs.edit().clear().apply()
}
}

View File

@ -0,0 +1,77 @@
package com.example.rehabilitation.Model
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import com.example.rehabilitation.databinding.ActivityEnternetBinding
/**
* Активность, отображаемая при отсутствии подключения к интернету
* Предоставляет пользователю информацию о проблеме и возможность повторить проверку
*/
class EnternetActivity : AppCompatActivity() {
// ViewBinding для безопасного доступа к UI элементам
private lateinit var binding: ActivityEnternetBinding
// Обработчик для обновления UI
private val handler = Handler(Looper.getMainLooper())
// Задержка между проверками подключения (в миллисекундах)
private val CHECK_DELAY = 2000L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityEnternetBinding.inflate(layoutInflater)
setContentView(binding.root)
// Настройка обработчиков нажатий
setupClickListeners()
// Запуск периодической проверки подключения
startConnectionCheck()
}
/**
* Настройка обработчиков нажатий на кнопки
*/
private fun setupClickListeners() {
// Обработчик нажатия на кнопку "Повторить"
binding.retryButton.setOnClickListener {
checkConnection()
}
// Обработчик нажатия на кнопку "Выход"
binding.exitButton.setOnClickListener {
finish()
}
}
/**
* Запуск периодической проверки подключения
*/
private fun startConnectionCheck() {
handler.postDelayed(object : Runnable {
override fun run() {
checkConnection()
handler.postDelayed(this, CHECK_DELAY)
}
}, CHECK_DELAY)
}
/**
* Проверка подключения к интернету
*/
private fun checkConnection() {
if (EnternetCheck.isInternetAvailable(this)) {
// Если подключение восстановлено, возвращаемся к предыдущей активности
finish()
}
}
override fun onDestroy() {
super.onDestroy()
// Останавливаем периодическую проверку при уничтожении активности
handler.removeCallbacksAndMessages(null)
}
}

View File

@ -0,0 +1,51 @@
package com.example.rehabilitation.Model
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
/**
* Объект для проверки состояния сетевого подключения
* Предоставляет методы для проверки доступности интернета и типа подключения
*/
object EnternetCheck {
/**
* Проверка наличия подключения к интернету
* @param context Контекст приложения
* @return true, если есть активное подключение к интернету, false в противном случае
*/
fun isInternetAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
/**
* Проверка типа подключения (Wi-Fi)
* @param context Контекст приложения
* @return true, если подключение осуществляется через Wi-Fi, false в противном случае
*/
fun isWifiConnection(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
}
/**
* Проверка типа подключения (мобильная сеть)
* @param context Контекст приложения
* @return true, если подключение осуществляется через мобильную сеть, false в противном случае
*/
fun isMobileConnection(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
}
}

View File

@ -0,0 +1,96 @@
package com.example.rehabilitation.Model
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.example.rehabilitation.databinding.FragmentQAfterBinding
/**
* Фрагмент для отображения и заполнения анкеты после занятий
* Позволяет пользователю оценить свое состояние после реабилитационной сессии
*/
class QAfterFragment : Fragment() {
// ViewBinding для безопасного доступа к UI элементам
private var _binding: FragmentQAfterBinding? = null
private val binding get() = _binding!!
// ViewModel для управления данными анкеты
private lateinit var viewModel: QuestionnaireViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentQAfterBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Инициализация ViewModel
viewModel = ViewModelProvider(this)[QuestionnaireViewModel::class.java]
// Настройка обработчиков нажатий
setupClickListeners()
// Наблюдение за изменениями в ViewModel
observeViewModel()
}
/**
* Настройка обработчиков нажатий на кнопки
*/
private fun setupClickListeners() {
// Обработчик нажатия на кнопку "Сохранить"
binding.saveButton.setOnClickListener {
saveQuestionnaire()
}
}
/**
* Сохранение данных анкеты
*/
private fun saveQuestionnaire() {
val questionnaire = Questionnaire(
id = 0, // Новый вопросник
patientId = viewModel.getPatientId(),
date = System.currentTimeMillis(),
painLevel = binding.painLevelSlider.value.toInt(),
moodLevel = binding.moodLevelSlider.value.toInt(),
fatigueLevel = binding.fatigueLevelSlider.value.toInt(),
notes = binding.notesEditText.text.toString()
)
viewModel.saveQuestionnaire(questionnaire)
}
/**
* Наблюдение за изменениями в ViewModel
*/
private fun observeViewModel() {
// Наблюдение за результатом сохранения
viewModel.saveResult.observe(viewLifecycleOwner) { result ->
when (result) {
is SaveResult.Success -> {
Toast.showShort(requireContext(), "Анкета успешно сохранена")
// Возврат к предыдущему экрану
requireActivity().onBackPressed()
}
is SaveResult.Error -> {
Toast.showLong(requireContext(), "Ошибка при сохранении анкеты: ${result.message}")
}
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -0,0 +1,8 @@
package com.example.rehabilitation.Model
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast

View File

@ -0,0 +1,110 @@
package com.example.rehabilitation.Model
/**
* Модель данных анкеты
* Содержит информацию о самочувствии пациента и его оценках
*/
data class Questionnaire(
// Уникальный идентификатор анкеты
val id: Int = 0,
// Тип анкеты (BEFORE - до занятий, AFTER - после занятий)
val type: String,
// ID пациента
val patientId: Int,
// Самочувствие пациента
val wellbeing: String,
// Уровень боли
val painLevel: String,
// Уровень усталости (только для анкеты после занятий)
val fatigueLevel: String? = null,
// Комментарий пациента
val comment: String,
// Дата и время заполнения анкеты
val timestamp: Long = System.currentTimeMillis()
) {
/**
* Преобразование модели в запрос для API
*/
fun toQuestionnaireRequest(): QuestionnaireRequest {
return QuestionnaireRequest(
type = type,
patientId = patientId,
wellbeing = wellbeing,
painLevel = painLevel,
fatigueLevel = fatigueLevel,
comment = comment
)
}
/**
* Проверка валидности данных анкеты
* @return true если данные валидны, false в противном случае
*/
fun isValid(): Boolean {
return type.isNotEmpty() &&
patientId > 0 &&
wellbeing.isNotEmpty() &&
painLevel.isNotEmpty() &&
comment.isNotEmpty() &&
(type != "AFTER" || fatigueLevel != null)
}
companion object {
/**
* Создание анкеты до занятий
*/
fun createBefore(
patientId: Int,
wellbeing: String,
painLevel: String,
comment: String
): Questionnaire {
return Questionnaire(
type = "BEFORE",
patientId = patientId,
wellbeing = wellbeing,
painLevel = painLevel,
comment = comment
)
}
/**
* Создание анкеты после занятий
*/
fun createAfter(
patientId: Int,
wellbeing: String,
painLevel: String,
fatigueLevel: String,
comment: String
): Questionnaire {
return Questionnaire(
type = "AFTER",
patientId = patientId,
wellbeing = wellbeing,
painLevel = painLevel,
fatigueLevel = fatigueLevel,
comment = comment
)
}
}
}
/**
* Модель запроса для API
*/
data class QuestionnaireRequest(
val type: String,
val patientId: Int,
val wellbeing: String,
val painLevel: String,
val fatigueLevel: String?,
val comment: String
)

View File

@ -0,0 +1,107 @@
package com.example.rehabilitation.Model
import com.example.rehabilitation.Network.ApiService
import com.example.rehabilitation.Network.QuestionnaireResponse
import com.example.rehabilitation.Pref.ConclusionPref
import retrofit2.Response
/**
* Репозиторий для работы с данными анкет
* Обеспечивает взаимодействие с API и локальным хранилищем
*/
class QuestionnaireRepository {
// Сервис для работы с API
private val apiService = ApiService.create()
// Менеджер настроек приложения
private val prefs = ConclusionPref()
/**
* Получение списка анкет для пациента
* @param patientId ID пациента
* @return Список анкет
* @throws Exception при ошибке получения данных
*/
suspend fun getQuestionnaires(patientId: Int): List<Questionnaire> {
val response = apiService.getQuestionnaires(patientId)
if (!response.isSuccessful) {
throw Exception("Ошибка при получении списка анкет: ${response.code()}")
}
return response.body() ?: emptyList()
}
/**
* Сохранение новой анкеты
* @param questionnaire Анкета для сохранения
* @return Сохраненная анкета
* @throws Exception при ошибке сохранения
*/
suspend fun saveQuestionnaire(questionnaire: Questionnaire): Questionnaire {
val response = apiService.saveQuestionnaire(questionnaire.toRequest())
if (!response.isSuccessful) {
throw Exception("Ошибка при сохранении анкеты: ${response.code()}")
}
return response.body() ?: throw Exception("Пустой ответ от сервера")
}
/**
* Обновление существующей анкеты
* @param questionnaire Анкета для обновления
* @return Обновленная анкета
* @throws Exception при ошибке обновления
*/
suspend fun updateQuestionnaire(questionnaire: Questionnaire): Questionnaire {
val response = apiService.updateQuestionnaire(questionnaire.id, questionnaire.toRequest())
if (!response.isSuccessful) {
throw Exception("Ошибка при обновлении анкеты: ${response.code()}")
}
return response.body() ?: throw Exception("Пустой ответ от сервера")
}
/**
* Удаление анкеты
* @param id ID анкеты для удаления
* @return true если удаление успешно
* @throws Exception при ошибке удаления
*/
suspend fun deleteQuestionnaire(id: Int): Boolean {
val response = apiService.deleteQuestionnaire(id)
if (!response.isSuccessful) {
throw Exception("Ошибка при удалении анкеты: ${response.code()}")
}
return true
}
/**
* Получение анкеты по ID
* @param id ID анкеты
* @return Анкета
* @throws Exception при ошибке получения или если анкета не найдена
*/
suspend fun getQuestionnaire(id: Int): Questionnaire {
val response = apiService.getQuestionnaire(id)
if (!response.isSuccessful) {
throw Exception("Ошибка при получении анкеты: ${response.code()}")
}
return response.body() ?: throw Exception("Анкета не найдена")
}
/**
* Получение ID пациента из настроек
* @return ID пациента
*/
fun getPatientId(): Int {
return prefs.getPatientId()
}
/**
* Проверка ответа сервера
* @param response Ответ сервера
* @throws Exception если ответ не успешен
*/
private fun checkResponse(response: Response<*>) {
if (!response.isSuccessful) {
throw Exception("Ошибка сервера: ${response.code()}")
}
}
}

View File

@ -0,0 +1,121 @@
package com.example.rehabilitation.Model
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
/**
* ViewModel для управления данными анкет
* Обрабатывает загрузку, сохранение и обновление анкет
*/
class QuestionnaireViewModel : ViewModel() {
// Репозиторий для работы с данными
private val repository = QuestionnaireRepository()
// LiveData для списка анкет
private val _questionnaires = MutableLiveData<List<Questionnaire>>()
val questionnaires: LiveData<List<Questionnaire>> = _questionnaires
// LiveData для индикации загрузки
private val _isLoading = MutableLiveData<Boolean>()
val isLoading: LiveData<Boolean> = _isLoading
// LiveData для результата сохранения
private val _saveResult = MutableLiveData<SaveResult>()
val saveResult: LiveData<SaveResult> = _saveResult
// LiveData для сообщений об ошибках
private val _error = MutableLiveData<String>()
val error: LiveData<String> = _error
/**
* Загрузка списка анкет для пациента
* @param patientId ID пациента
*/
fun loadQuestionnaires(patientId: Int) {
viewModelScope.launch {
_isLoading.value = true
try {
val result = repository.getQuestionnaires(patientId)
_questionnaires.value = result
} catch (e: Exception) {
_error.value = "Ошибка при загрузке анкет: ${e.message}"
} finally {
_isLoading.value = false
}
}
}
/**
* Сохранение новой анкеты
* @param questionnaire Анкета для сохранения
*/
fun saveQuestionnaire(questionnaire: Questionnaire) {
viewModelScope.launch {
_isLoading.value = true
try {
val result = repository.saveQuestionnaire(questionnaire)
_saveResult.value = SaveResult.Success(result)
} catch (e: Exception) {
_saveResult.value = SaveResult.Error(e.message ?: "Неизвестная ошибка")
} finally {
_isLoading.value = false
}
}
}
/**
* Обновление существующей анкеты
* @param questionnaire Анкета для обновления
*/
fun updateQuestionnaire(questionnaire: Questionnaire) {
viewModelScope.launch {
_isLoading.value = true
try {
val result = repository.updateQuestionnaire(questionnaire)
_saveResult.value = SaveResult.Success(result)
} catch (e: Exception) {
_saveResult.value = SaveResult.Error(e.message ?: "Неизвестная ошибка")
} finally {
_isLoading.value = false
}
}
}
/**
* Удаление анкеты
* @param questionnaireId ID анкеты для удаления
*/
fun deleteQuestionnaire(questionnaireId: Int) {
viewModelScope.launch {
_isLoading.value = true
try {
repository.deleteQuestionnaire(questionnaireId)
// Обновляем список анкет после удаления
loadQuestionnaires(repository.getPatientId())
} catch (e: Exception) {
_error.value = "Ошибка при удалении анкеты: ${e.message}"
} finally {
_isLoading.value = false
}
}
}
/**
* Получение ID пациента из репозитория
* @return ID пациента
*/
fun getPatientId(): Int {
return repository.getPatientId()
}
}
/**
* Результат операции сохранения
*/
sealed class SaveResult {
data class Success(val questionnaire: Questionnaire) : SaveResult()
data class Error(val message: String) : SaveResult()
}

View File

@ -0,0 +1,52 @@
package com.example.rehabilitation.Model
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
/**
* Клиент для работы с Retrofit
* Отвечает за настройку и создание экземпляра Retrofit с необходимыми параметрами
*/
object RetrofitClient {
// Таймаут для HTTP-запросов (в секундах)
private const val TIMEOUT = 30L
/**
* Создание экземпляра Retrofit с настройками
* @param baseUrl Базовый URL API
* @return Экземпляр Retrofit
*/
fun create(baseUrl: String): Retrofit {
// Создание логгера для HTTP-запросов
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
// Настройка HTTP-клиента
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
.readTimeout(TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
.build()
// Создание и настройка экземпляра Retrofit
return Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
/**
* Создание сервиса API
* @param baseUrl Базовый URL API
* @return Экземпляр ApiService
*/
fun createService(baseUrl: String): ApiService {
return create(baseUrl).create(ApiService::class.java)
}
}

View File

@ -0,0 +1,28 @@
package com.example.rehabilitation.Model
import android.content.Context
import android.widget.Toast
/**
* Объект для удобного отображения уведомлений Toast
* Предоставляет методы для показа коротких и длинных уведомлений
*/
object Toast {
/**
* Показывает короткое уведомление
* @param context Контекст приложения
* @param message Текст уведомления
*/
fun showShort(context: Context, message: String) {
android.widget.Toast.makeText(context, message, android.widget.Toast.LENGTH_SHORT).show()
}
/**
* Показывает длинное уведомление
* @param context Контекст приложения
* @param message Текст уведомления
*/
fun showLong(context: Context, message: String) {
android.widget.Toast.makeText(context, message, android.widget.Toast.LENGTH_LONG).show()
}
}

View File

@ -0,0 +1,147 @@
package com.example.rehabilitation
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.rehabilitation.Model.Patient
import com.example.rehabilitation.Model.PatientRepository
import com.example.rehabilitation.Model.Questionnaire
import com.example.rehabilitation.Model.QuestionnaireRepository
import kotlinx.coroutines.launch
import com.example.rehabilitation.Appeals.TabLayout.Model.AppealsNewModel
import com.example.rehabilitation.Appeals.TabLayout.Model.AppealsOldModel
import com.example.rehabilitation.Calendare.CalendareModel
import com.example.rehabilitation.Questionnaire.Model.AfterLookModel
import com.example.rehabilitation.Questionnaire.Model.BeforeLookModel
import com.example.rehabilitation.Sport.SportDayOneModel
import com.example.rehabilitation.Sport.ViewVisibleModel
/**
* ViewModel для управления данными пациента
* Отвечает за загрузку и обновление информации о пациенте и его анкетах
*/
class PatientViewModel : ViewModel() {
// Репозиторий для работы с данными пациента
private val patientRepository = PatientRepository()
// Репозиторий для работы с анкетами
private val questionnaireRepository = QuestionnaireRepository()
// LiveData для хранения данных пациента
private val _patient = MutableLiveData<Patient>()
val patient: LiveData<Patient> = _patient
// LiveData для хранения списка анкет
private val _questionnaires = MutableLiveData<List<Questionnaire>>()
val questionnaires: LiveData<List<Questionnaire>> = _questionnaires
// LiveData для хранения статуса загрузки
private val _isLoading = MutableLiveData<Boolean>()
val isLoading: LiveData<Boolean> = _isLoading
// LiveData для хранения ошибок
private val _error = MutableLiveData<String>()
val error: LiveData<String> = _error
// Токен авторизации
val token = MutableLiveData<String>()
// Данные о спортивных занятиях на день
val liveDaySportOne = MutableLiveData<SportDayOneModel>()
// Данные о новых (необработанных) обращениях
val appealsNewCurrent = MutableLiveData<AppealsNewModel>()
val appealsNewList = MutableLiveData<List<AppealsNewModel>>()
// Данные об обработанных обращениях
val appealsOldCurrent = MutableLiveData<AppealsOldModel>()
val appealsOldList = MutableLiveData<List<AppealsOldModel>>()
// Данные о текущем виде экрана
val viewCurrent = MutableLiveData<ViewVisibleModel>()
// Данные календаря
val calendareList = MutableLiveData<List<CalendareModel>>()
// Данные анкетирования после занятий
val afterLook = MutableLiveData<AfterLookModel>()
// Данные анкетирования до занятий
val beforeLook = MutableLiveData<BeforeLookModel>()
// val productList = MutableLiveData<List<Product>>()
/**
* Загрузка данных пациента
* @param patientId ID пациента
*/
fun loadPatient(patientId: Int) {
viewModelScope.launch {
try {
_isLoading.value = true
val result = patientRepository.getPatient(patientId)
_patient.value = result
_error.value = null
} catch (e: Exception) {
_error.value = e.message
} finally {
_isLoading.value = false
}
}
}
/**
* Загрузка списка анкет пациента
* @param patientId ID пациента
*/
fun loadQuestionnaires(patientId: Int) {
viewModelScope.launch {
try {
_isLoading.value = true
val result = questionnaireRepository.getQuestionnaires(patientId)
_questionnaires.value = result
_error.value = null
} catch (e: Exception) {
_error.value = e.message
} finally {
_isLoading.value = false
}
}
}
/**
* Обновление данных пациента
* @param patient Обновленные данные пациента
*/
fun updatePatient(patient: Patient) {
viewModelScope.launch {
try {
_isLoading.value = true
patientRepository.updatePatient(patient)
_patient.value = patient
_error.value = null
} catch (e: Exception) {
_error.value = e.message
} finally {
_isLoading.value = false
}
}
}
/**
* Сохранение новой анкеты
* @param questionnaire Данные анкеты
*/
fun saveQuestionnaire(questionnaire: Questionnaire) {
viewModelScope.launch {
try {
_isLoading.value = true
questionnaireRepository.saveQuestionnaire(questionnaire)
loadQuestionnaires(questionnaire.patientId)
_error.value = null
} catch (e: Exception) {
_error.value = e.message
} finally {
_isLoading.value = false
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More