Compare commits

..

5 Commits

64 changed files with 2278 additions and 639 deletions

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-feature android:name="android.hardware.camera.any" /> <uses-feature android:name="android.hardware.camera.any" />
@ -7,24 +8,22 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application <application
android:allowBackup="false" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/application_icon" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:usesCleartextTraffic="true" android:theme="@style/Theme.Default"
android:theme="@style/splashScreenTheme"> tools:targetApi="31">
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyBtIU8oX16f9I0oLvoevw2T332vr10_Sw8"/>
<activity <activity
android:name=".ui.screens.LoginActivity" android:name=".ui.main.MainActivity"
android:exported="false" /> android:exported="false" />
<activity <activity
android:name=".ui.screens.MainActivity" android:name=".ui.login.LoginActivity"
android:exported="true" > android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -32,4 +31,5 @@
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>
</manifest>
</manifest>

@ -5,11 +5,13 @@ import androidx.annotation.NonNull;
import ru.myitschool.work.api.data.dto.employee.EmployeeDTO; import ru.myitschool.work.api.data.dto.employee.EmployeeDTO;
import ru.myitschool.work.api.data.network.RetrofitFactory; import ru.myitschool.work.api.data.network.RetrofitFactory;
import ru.myitschool.work.api.data.source.EmployeeApi; import ru.myitschool.work.api.data.source.EmployeeApi;
import ru.myitschool.work.api.data.utils.CallToConsumer;
import ru.myitschool.work.api.domain.EmployeeRepository; import ru.myitschool.work.api.domain.EmployeeRepository;
import ru.myitschool.work.api.domain.entity.Status; import ru.myitschool.work.api.domain.entity.Status;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
import ru.myitschool.work.api.domain.entity.employee.ItemEmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.ItemEmployeeEntity;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -83,22 +85,22 @@ public class EmployeeRepositoryImpl implements EmployeeRepository {
// } // }
@Override @Override
public void getAllEmployees(@NonNull Consumer<Status<List<EmployeeEntity>>> callback) { public void getAllEmployees(@NonNull Consumer<Status<List<EmpolyeeEntity>>> callback) {
} }
@Override @Override
public ItemEmployeeEntity getEmployeeById(long id, @NonNull Consumer<Status<EmployeeEntity>> callback) { public ItemEmployeeEntity getEmployeeById(long id, @NonNull Consumer<Status<EmpolyeeEntity>> callback) {
return null; return null;
} }
@Override @Override
public void getEmployeeByEmail(@NonNull String email, @NonNull Consumer<Status<EmployeeEntity>> callback) { public void getEmployeeByEmail(@NonNull String email, @NonNull Consumer<Status<EmpolyeeEntity>> callback) {
} }
@Override @Override
public void getEmployeeByTelephone(@NonNull String telephone, @NonNull Consumer<Status<EmployeeEntity>> callback) { public void getEmployeeByTelephone(@NonNull String telephone, @NonNull Consumer<Status<EmpolyeeEntity>> callback) {
} }
@ -108,7 +110,7 @@ public class EmployeeRepositoryImpl implements EmployeeRepository {
} }
@Override @Override
public void deleteEmployee(long id, @NonNull Consumer<Status<EmployeeEntity>> callback) { public void deleteEmployee(long id, @NonNull Consumer<Status<EmpolyeeEntity>> callback) {
} }

@ -1,7 +1,5 @@
package ru.myitschool.work.api.data; package ru.myitschool.work.api.data;
import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import java.util.List; import java.util.List;
@ -13,7 +11,7 @@ import ru.myitschool.work.api.data.source.SignApi;
import ru.myitschool.work.api.data.utils.CallToConsumer; import ru.myitschool.work.api.data.utils.CallToConsumer;
import ru.myitschool.work.api.domain.SignRepository; import ru.myitschool.work.api.domain.SignRepository;
import ru.myitschool.work.api.domain.entity.Status; import ru.myitschool.work.api.domain.entity.Status;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
public class SignRepositoryImpl implements SignRepository { public class SignRepositoryImpl implements SignRepository {
private static SignRepositoryImpl INSTANCE; private static SignRepositoryImpl INSTANCE;
@ -29,7 +27,7 @@ public class SignRepositoryImpl implements SignRepository {
} }
@Override @Override
public void createEmployee(@NonNull EmployeeCreateDTO employeeCreateDTO, @NonNull Consumer<Status<EmployeeEntity>> callback) { public void createEmployee(@NonNull EmployeeCreateDTO employeeCreateDTO, @NonNull Consumer<Status<EmpolyeeEntity>> callback) {
signApi.register(employeeCreateDTO).enqueue(new CallToConsumer<>( signApi.register(employeeCreateDTO).enqueue(new CallToConsumer<>(
callback, callback,
employeeDTO -> { employeeDTO -> {
@ -44,27 +42,32 @@ public class SignRepositoryImpl implements SignRepository {
final long officeId = employeeDTO.officeId; final long officeId = employeeDTO.officeId;
final String officeName = employeeDTO.officeName; final String officeName = employeeDTO.officeName;
final String officeUrl= employeeDTO.officeImageUrl; final String officeUrl= employeeDTO.officeImageUrl;
final String position = employeeDTO.position; final String possition = employeeDTO.position;
final String role = employeeDTO.role; final String role = employeeDTO.role;
final String profileImageUrl= employeeDTO.profileImageUrl; final String profileImageUrl= employeeDTO.profileImageUrl;
final boolean visitStatus= employeeDTO.visitStatus; final boolean visitStatus= employeeDTO.visitStatus;
final String startVisit= employeeDTO.startVisitDateTime; final String startVisit= employeeDTO.startVisitDateTime;
final List<Long> visitIdLast30Days = employeeDTO.visitsIdLast30Days; final List<Long> visitIdLast30Days = employeeDTO.visitsIdLast30Days;
final long totalVisitTimeLast30Days = employeeDTO.totalTimeVisitsLast30Days; final long totalVisitTimeLast30Days = employeeDTO.totalTimeVisitsLast30Days;
final String currentOfficeName = employeeDTO.currentOfficeName; final String curentOfficeName = employeeDTO.currentOfficeName;
final String createdAt= employeeDTO.createAt; final String createdAt= employeeDTO.createAt;
if (name != null && surname != null && telephone != null && email_ != null && officeName != null && officeUrl != null && position != null && if (name != null && surname != null && telephone != null &&
role != null && startVisit != null && profileImageUrl != null && visitIdLast30Days != null && currentOfficeName != null && createdAt != null) { email_ != null && officeName != null && officeUrl != null &&
return new EmployeeEntity(id_, name, surname, patronymic, telephone, email_, officeId, officeName, officeUrl, position, role, profileImageUrl, possition != null && role != null && startVisit != null &&
visitStatus, startVisit, visitIdLast30Days, totalVisitTimeLast30Days, currentOfficeName, createdAt); visitIdLast30Days != null && curentOfficeName != null &&
createdAt != null) {
return new EmpolyeeEntity(id_, name, surname, patronymic,
telephone, email_, officeId, officeName, officeUrl, possition, role, profileImageUrl,
visitStatus, startVisit, visitIdLast30Days, totalVisitTimeLast30Days, curentOfficeName, createdAt);
} else return null; } else return null;
}) })
); );
} }
@Override @Override
public void login(@NonNull String email, @NonNull String password, @NonNull Consumer<Status<EmployeeEntity>> callback) { public void login(@NonNull String email, @NonNull String password, @NonNull Consumer<Status<EmpolyeeEntity>> callback) {
credentialsDataSource.updateLogin(email, password); credentialsDataSource.updateLogin(email, password);
signApi.login().enqueue(new CallToConsumer<>(callback, employeeDTO -> { signApi.login().enqueue(new CallToConsumer<>(callback, employeeDTO -> {
if (employeeDTO == null) return null; if (employeeDTO == null) return null;
@ -78,22 +81,25 @@ public class SignRepositoryImpl implements SignRepository {
final long officeId = employeeDTO.officeId; final long officeId = employeeDTO.officeId;
final String officeName = employeeDTO.officeName; final String officeName = employeeDTO.officeName;
final String officeUrl= employeeDTO.officeImageUrl; final String officeUrl= employeeDTO.officeImageUrl;
final String position = employeeDTO.position; final String possition = employeeDTO.position;
final String role = employeeDTO.role; final String role = employeeDTO.role;
final String profileImageUrl = employeeDTO.profileImageUrl; final String profileImageUrl= employeeDTO.profileImageUrl;
final boolean visitStatus= employeeDTO.visitStatus; final boolean visitStatus= employeeDTO.visitStatus;
final String startVisit = employeeDTO.startVisitDateTime; final String startVisit= employeeDTO.startVisitDateTime;
final List<Long> visitIdLast30Days = employeeDTO.visitsIdLast30Days; final List<Long> visitIdLast30Days = employeeDTO.visitsIdLast30Days;
final long totalVisitTimeLast30Days = employeeDTO.totalTimeVisitsLast30Days; final long totalVisitTimeLast30Days = employeeDTO.totalTimeVisitsLast30Days;
final String currentOfficeName = employeeDTO.currentOfficeName; final String curentOfficeName = employeeDTO.currentOfficeName;
final String createdAt = employeeDTO.createAt; final String createdAt= employeeDTO.createAt;
if (name != null && surname != null && telephone != null && email_ != null && officeName != null && officeUrl != null if (name != null && surname != null && telephone != null &&
&& position != null && role != null && profileImageUrl != null && startVisit != null && visitIdLast30Days != null email_ != null && officeName != null && officeUrl != null &&
&& currentOfficeName != null && createdAt != null) { possition != null && role != null && startVisit != null &&
visitIdLast30Days != null && curentOfficeName != null &&
createdAt != null) {
return new EmployeeEntity(id_, name, surname, patronymic, telephone, email_, officeId, officeName, officeUrl, position, role, profileImageUrl, return new EmpolyeeEntity(id_, name, surname, patronymic,
visitStatus, startVisit, visitIdLast30Days, totalVisitTimeLast30Days, currentOfficeName, createdAt); telephone, email_, officeId, officeName, officeUrl, possition, role, profileImageUrl,
visitStatus, startVisit, visitIdLast30Days, totalVisitTimeLast30Days, curentOfficeName, createdAt);
} else return null; } else return null;
})); }));
} }

@ -36,7 +36,7 @@ public class EmployeeDTO {
@SerializedName("officeImageUrl") @SerializedName("officeImageUrl")
public String officeImageUrl; public String officeImageUrl;
@Nullable @Nullable
@SerializedName("positionName") @SerializedName("position")
public String position; // Название должности public String position; // Название должности
@Nullable @Nullable
@SerializedName("role") @SerializedName("role")

@ -1,6 +1,6 @@
package ru.myitschool.work.api.data.network; package ru.myitschool.work.api.data.network;
import ru.myitschool.work.core.UrlConstants; import com.example.myapplication.core.UrlConstants;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;

@ -9,9 +9,10 @@ import ru.myitschool.work.api.data.dto.employee.EmployeeCreateDTO;
import ru.myitschool.work.api.data.dto.employee.EmployeeDTO; import ru.myitschool.work.api.data.dto.employee.EmployeeDTO;
public interface SignApi { public interface SignApi {
@POST("api/v1/authorization/register") @POST("api/v1/employees/authorization/register")
Call<EmployeeDTO> register(@Body EmployeeCreateDTO employeeCreateDTO); Call<EmployeeDTO> register(@Body EmployeeCreateDTO employeeCreateDTO);
@GET("api/v1/authorization/login") @GET("api/v1/employees/authorization//login")
Call<EmployeeDTO> login(); Call<EmployeeDTO> login();
} }

@ -7,15 +7,15 @@ import java.util.function.Consumer;
import ru.myitschool.work.api.data.dto.employee.EmployeeDTO; import ru.myitschool.work.api.data.dto.employee.EmployeeDTO;
import ru.myitschool.work.api.domain.entity.Status; import ru.myitschool.work.api.domain.entity.Status;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
import ru.myitschool.work.api.domain.entity.employee.ItemEmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.ItemEmployeeEntity;
public interface EmployeeRepository { public interface EmployeeRepository {
void getAllEmployees(@NonNull Consumer<Status<List<EmployeeEntity>>> callback); void getAllEmployees(@NonNull Consumer<Status<List<EmpolyeeEntity>>> callback);
ItemEmployeeEntity getEmployeeById(long id, @NonNull Consumer<Status<EmployeeEntity>> callback); ItemEmployeeEntity getEmployeeById(long id, @NonNull Consumer<Status<EmpolyeeEntity>> callback);
void getEmployeeByEmail(@NonNull String email, @NonNull Consumer<Status<EmployeeEntity>> callback); void getEmployeeByEmail(@NonNull String email, @NonNull Consumer<Status<EmpolyeeEntity>> callback);
void getEmployeeByTelephone(@NonNull String telephone, @NonNull Consumer<Status<EmployeeEntity>> callback); void getEmployeeByTelephone(@NonNull String telephone, @NonNull Consumer<Status<EmpolyeeEntity>> callback);
void updateEmployee(long id, @NonNull EmployeeDTO employeeDTO, @NonNull Consumer<Status<Void>> callback);//переделай после dto void updateEmployee(long id, @NonNull EmployeeDTO employeeDTO, @NonNull Consumer<Status<Void>> callback);//переделай после dto
void deleteEmployee(long id, @NonNull Consumer<Status<EmployeeEntity>> callback); void deleteEmployee(long id, @NonNull Consumer<Status<EmpolyeeEntity>> callback);
void patchEmployeerOfficeId(long id, long officeId, @NonNull Consumer<Status<Void>> callback); void patchEmployeerOfficeId(long id, long officeId, @NonNull Consumer<Status<Void>> callback);
} }

@ -6,10 +6,10 @@ import java.util.function.Consumer;
import ru.myitschool.work.api.data.dto.employee.EmployeeCreateDTO; import ru.myitschool.work.api.data.dto.employee.EmployeeCreateDTO;
import ru.myitschool.work.api.domain.entity.Status; import ru.myitschool.work.api.domain.entity.Status;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
public interface SignRepository { public interface SignRepository {
void createEmployee(@NonNull EmployeeCreateDTO employeeRegisterDTO, @NonNull Consumer<Status<EmployeeEntity>> callback); void createEmployee(@NonNull EmployeeCreateDTO employeeRegisterDTO, @NonNull Consumer<Status<EmpolyeeEntity>> callback);
void login(@NonNull String email, @NonNull String password, @NonNull Consumer<Status<EmployeeEntity>> callback); void login(@NonNull String email, @NonNull String password, @NonNull Consumer<Status<EmpolyeeEntity>> callback);
void logout(); void logout();
} }

@ -1,20 +1,21 @@
package ru.myitschool.work.api.domain.entity; package ru.myitschool.work.api.domain.entity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
public class Status<T> { public class Status<T> {
final int statusCode; final int statusCod;
@Nullable private final T value; @Nullable private final T value;
@Nullable private final Throwable errors; @Nullable private final Throwable errors;
public Status(int statusCode, @Nullable T value, @Nullable Throwable errors) { public Status(int statusCod, @Nullable T value, @Nullable Throwable errors) {
this.statusCode = statusCode; this.statusCod = statusCod;
this.value = value; this.value = value;
this.errors = errors; this.errors = errors;
} }
public int getStatusCode() { public int getStatusCod() {
return statusCode; return statusCod;
} }
@Nullable @Nullable

@ -3,17 +3,18 @@ package ru.myitschool.work.api.domain.entity.employee;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.util.Date;
import java.util.List; import java.util.List;
public class EmployeeEntity { public class EmpolyeeEntity {
private final long id; @NonNull private final long id;
@NonNull private final String name; @NonNull private final String name;
@NonNull private final String surname; @NonNull private final String surname;
@Nullable private final String patronymic; @NonNull private final String patronymic;
@NonNull private final String telephone; @NonNull private final String telephone;
@NonNull private final String email; @NonNull private final String email;
private final long officeId; @NonNull private final long officeId;
@NonNull private final String officeName; @NonNull private final String officeName;
@NonNull private final String officeImageUrl; @NonNull private final String officeImageUrl;
@ -23,7 +24,7 @@ public class EmployeeEntity {
@NonNull private final String profileImageUrl; @NonNull private final String profileImageUrl;
// Текущее состояние входа: false - visit (посещение) ещё не началось, true - visit идёт // Текущее состояние входа: false - visit (посещение) ещё не началось, true - visit идёт
private final boolean visitStatus; @NonNull private final boolean visitStatus;
// Если visitStatus true, то возвращает дату и время начала посещения в формате LocalDateTime.toString(), // Если visitStatus true, то возвращает дату и время начала посещения в формате LocalDateTime.toString(),
// превратить обратно можно с помощью LocalDateTime.parse(). // превратить обратно можно с помощью LocalDateTime.parse().
@ -32,7 +33,7 @@ public class EmployeeEntity {
@NonNull private final List<Long> visitsIdLast30Days; // Список Id посещений за последние 30 дней. @NonNull private final List<Long> visitsIdLast30Days; // Список Id посещений за последние 30 дней.
// Возвращает количество отработанных часов за последний месяц. // Возвращает количество отработанных часов за последний месяц.
private final long totalTimeVisitsLast30Days; @NonNull private final long totalTimeVisitsLast30Days;
// (Возможно это стоит убрать) Название офиса, в котором сейчас находится работник. // (Возможно это стоит убрать) Название офиса, в котором сейчас находится работник.
// Если visitStatus false, возвращает null. // Если visitStatus false, возвращает null.
@ -42,7 +43,7 @@ public class EmployeeEntity {
// превратить обратно можно с помощью LocalDateTime.parse(). // превратить обратно можно с помощью LocalDateTime.parse().
@NonNull private final String createAt; @NonNull private final String createAt;
public EmployeeEntity(long id, @NonNull String name, @NonNull String surname, @Nullable String patronymic, @NonNull String telephone, @NonNull String email, long officeId, @NonNull String officeName, @NonNull String officeImageUrl, @NonNull String position, @NonNull String role, @NonNull String profileImageUrl, boolean visitStatus, @NonNull String startVisitDateTime, @NonNull List<Long> visitsIdLast30Days, long totalTimeVisitsLast30Days, @NonNull String currentOfficeName, @NonNull String createAt) { public EmpolyeeEntity(long id, @NonNull String name, @NonNull String surname, @NonNull String patronymic, @NonNull String telephone, @NonNull String email, long officeId, @NonNull String officeName, @NonNull String officeImageUrl, @NonNull String position, @NonNull String role, @NonNull String profileImageUrl, boolean visitStatus, @NonNull String startVisitDateTime, @NonNull List<Long> visitsIdLast30Days, long totalTimeVisitsLast30Days, @NonNull String currentOfficeName, @NonNull String createAt) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.surname = surname; this.surname = surname;
@ -63,76 +64,13 @@ public class EmployeeEntity {
this.createAt = createAt; this.createAt = createAt;
} }
@NonNull public long getId() {
public String getCreateAt() { return id;
return createAt;
} }
@NonNull @NonNull
public String getCurrentOfficeName() { public String getName() {
return currentOfficeName; return name;
}
public long getTotalTimeVisitsLast30Days() {
return totalTimeVisitsLast30Days;
}
@NonNull
public List<Long> getVisitsIdLast30Days() {
return visitsIdLast30Days;
}
@NonNull
public String getStartVisitDateTime() {
return startVisitDateTime;
}
public boolean isVisitStatus() {
return visitStatus;
}
@NonNull
public String getProfileImageUrl() {
return profileImageUrl;
}
@NonNull
public String getRole() {
return role;
}
@NonNull
public String getPosition() {
return position;
}
@NonNull
public String getOfficeImageUrl() {
return officeImageUrl;
}
@NonNull
public String getOfficeName() {
return officeName;
}
public long getOfficeId() {
return officeId;
}
@NonNull
public String getEmail() {
return email;
}
@NonNull
public String getTelephone() {
return telephone;
}
@Nullable
public String getPatronymic() {
return patronymic;
} }
@NonNull @NonNull
@ -141,11 +79,74 @@ public class EmployeeEntity {
} }
@NonNull @NonNull
public String getName() { public String getPatronymic() {
return name; return patronymic;
} }
public long getId() { @NonNull
return id; public String getTelephone() {
return telephone;
}
@NonNull
public String getEmail() {
return email;
}
public long getOfficeId() {
return officeId;
}
@NonNull
public String getOfficeName() {
return officeName;
}
@NonNull
public String getOfficeImageUrl() {
return officeImageUrl;
}
@NonNull
public String getPosition() {
return position;
}
@NonNull
public String getRole() {
return role;
}
@NonNull
public String getProfileImageUrl() {
return profileImageUrl;
}
public boolean isVisitStatus() {
return visitStatus;
}
@NonNull
public String getStartVisitDateTime() {
return startVisitDateTime;
}
@NonNull
public List<Long> getVisitsIdLast30Days() {
return visitsIdLast30Days;
}
public long getTotalTimeVisitsLast30Days() {
return totalTimeVisitsLast30Days;
}
@NonNull
public String getCurrentOfficeName() {
return currentOfficeName;
}
@NonNull
public String getCreateAt() {
return createAt;
} }
} }

@ -6,7 +6,7 @@ import java.util.function.Consumer;
import ru.myitschool.work.api.domain.EmployeeRepository; import ru.myitschool.work.api.domain.EmployeeRepository;
import ru.myitschool.work.api.domain.entity.Status; import ru.myitschool.work.api.domain.entity.Status;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
public class DeleteEmployeeUseCase { public class DeleteEmployeeUseCase {
private final EmployeeRepository employeeRepository; private final EmployeeRepository employeeRepository;
@ -16,7 +16,7 @@ public class DeleteEmployeeUseCase {
} }
public void execute(long id, @NonNull Consumer<Status<EmployeeEntity>> callback) { public void execute(long id, @NonNull Consumer<Status<EmpolyeeEntity>> callback) {
employeeRepository.deleteEmployee(id,callback); employeeRepository.deleteEmployee(id,callback);
} }
} }

@ -7,7 +7,7 @@ import java.util.function.Consumer;
import ru.myitschool.work.api.domain.EmployeeRepository; import ru.myitschool.work.api.domain.EmployeeRepository;
import ru.myitschool.work.api.domain.entity.Status; import ru.myitschool.work.api.domain.entity.Status;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
public class GetAllEmployees { public class GetAllEmployees {
private final EmployeeRepository employeeRepository; private final EmployeeRepository employeeRepository;
@ -16,7 +16,7 @@ public class GetAllEmployees {
this.employeeRepository = employeeRepository; this.employeeRepository = employeeRepository;
} }
public void execute(@NonNull Consumer<Status<List<EmployeeEntity>>> callback) { public void execute(@NonNull Consumer<Status<List<EmpolyeeEntity>>> callback) {
employeeRepository.getAllEmployees(callback); employeeRepository.getAllEmployees(callback);
} }
} }

@ -8,7 +8,7 @@ import java.util.function.Consumer;
import ru.myitschool.work.api.domain.EmployeeRepository; import ru.myitschool.work.api.domain.EmployeeRepository;
import ru.myitschool.work.api.domain.entity.Status; import ru.myitschool.work.api.domain.entity.Status;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
public class GetEmloyeeByIdUseCase { public class GetEmloyeeByIdUseCase {
private final EmployeeRepository employeeRepository; private final EmployeeRepository employeeRepository;
@ -17,7 +17,7 @@ public class GetEmloyeeByIdUseCase {
this.employeeRepository = employeeRepository; this.employeeRepository = employeeRepository;
} }
public void execute(long id, @NonNull Consumer<Status<EmployeeEntity>> callback) { public void execute(long id, @NonNull Consumer<Status<EmpolyeeEntity>> callback) {
employeeRepository.getEmployeeById(id, callback); employeeRepository.getEmployeeById(id, callback);
} }
} }

@ -6,7 +6,7 @@ import java.util.function.Consumer;
import ru.myitschool.work.api.domain.EmployeeRepository; import ru.myitschool.work.api.domain.EmployeeRepository;
import ru.myitschool.work.api.domain.entity.Status; import ru.myitschool.work.api.domain.entity.Status;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
public class GetEmployeeByEmailUseCase { public class GetEmployeeByEmailUseCase {
private final ru.myitschool.work.api.domain.EmployeeRepository employeeRepository; private final ru.myitschool.work.api.domain.EmployeeRepository employeeRepository;
@ -15,6 +15,6 @@ public class GetEmployeeByEmailUseCase {
this.employeeRepository = employeeRepository; this.employeeRepository = employeeRepository;
} }
public void execute(@NonNull String email, @NonNull Consumer<Status<EmployeeEntity>> callback) { public void execute(@NonNull String email, @NonNull Consumer<Status<EmpolyeeEntity>> callback) {
employeeRepository.getEmployeeByEmail(email, callback); employeeRepository.getEmployeeByEmail(email, callback);
}} }}

@ -7,7 +7,7 @@ import java.util.function.Consumer;
import ru.myitschool.work.api.data.dto.employee.EmployeeCreateDTO; import ru.myitschool.work.api.data.dto.employee.EmployeeCreateDTO;
import ru.myitschool.work.api.domain.SignRepository; import ru.myitschool.work.api.domain.SignRepository;
import ru.myitschool.work.api.domain.entity.Status; import ru.myitschool.work.api.domain.entity.Status;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
public class CreateEmployeeUseCase { public class CreateEmployeeUseCase {
private final SignRepository signRepository; private final SignRepository signRepository;
@ -16,7 +16,7 @@ public class CreateEmployeeUseCase {
this.signRepository = signRepository; this.signRepository = signRepository;
} }
public void execute(@NonNull EmployeeCreateDTO employeeRegisterDTO, Consumer<Status<EmployeeEntity>> callback) { public void execute(@NonNull EmployeeCreateDTO employeeRegisterDTO, Consumer<Status<EmpolyeeEntity>> callback) {
signRepository.createEmployee(employeeRegisterDTO, callback); signRepository.createEmployee(employeeRegisterDTO, callback);
} }
} }

@ -6,7 +6,7 @@ import java.util.function.Consumer;
import ru.myitschool.work.api.domain.SignRepository; import ru.myitschool.work.api.domain.SignRepository;
import ru.myitschool.work.api.domain.entity.Status; import ru.myitschool.work.api.domain.entity.Status;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
public class LoginEmployeeUseCase { public class LoginEmployeeUseCase {
private final SignRepository signRepository; private final SignRepository signRepository;
@ -15,9 +15,9 @@ public class LoginEmployeeUseCase {
this.signRepository = signRepository; this.signRepository = signRepository;
} }
public void execute(@NonNull String email, @NonNull String password, Consumer<Status<EmployeeEntity>> callback) { public void execute(@NonNull String email, @NonNull String password, Consumer<Status<EmpolyeeEntity>> callback) {
signRepository.login(email, password, employeeEntityStatus -> { signRepository.login(email, password, employeeEntityStatus -> {
if (employeeEntityStatus.getStatusCode() != 200) signRepository.logout(); //if (employeeEntityStatus.getStatusCode() != 200) signRepository.logout();
callback.accept(employeeEntityStatus); callback.accept(employeeEntityStatus);
}); });
} }

@ -1,6 +1,7 @@
package ru.myitschool.work.core package com.example.myapplication.core
object UrlConstants { object UrlConstants {
// url для эмулятора http://10.0.2.2:8080/ // url для эмулятора http://10.0.2.2:8080/
const val BASE_URL: String = "http://10.6.66.151:8080" const val BASE_URL: String = "http://192.168.0.105:8080"
const val DOWNLOAD_URL: String = "$BASE_URL/api/v1/images/"
} }

@ -0,0 +1,38 @@
package ru.myitschool.work.ui.createemployee;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import ru.myitschool.work.R;
public class CreateUserFragment extends Fragment {
private CreateUserViewModel mViewModel;
public static CreateUserFragment newInstance() {
return new CreateUserFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_create_user, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = new ViewModelProvider(this).get(CreateUserViewModel.class);
// TODO: Use the ViewModel
}
}

@ -0,0 +1,7 @@
package ru.myitschool.work.ui.createemployee;
import androidx.lifecycle.ViewModel;
public class CreateUserViewModel extends ViewModel {
// TODO: Implement the ViewModel
}

@ -0,0 +1,115 @@
package ru.myitschool.work.ui.login;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.lifecycle.ViewModelProvider;
import com.example.myapplication.core.SettingConstants;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.textfield.TextInputEditText;
import ru.myitschool.work.R;
import ru.myitschool.work.databinding.ActivityLoginBinding;
import ru.myitschool.work.ui.main.MainActivity;
public class LoginActivity extends AppCompatActivity {
private ActivityLoginBinding binding;
private LoginViewModel viewModel;
public LoginActivity() {
super(R.layout.activity_login);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_login);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
binding = ActivityLoginBinding.bind(v);
viewModel = new ViewModelProvider(this).get(LoginViewModel.class);
binding.email.addTextChangedListener(new TextChangedListener<>(binding.email) {
@Override
public void onTextChanged(TextInputEditText target, Editable s) {
listenerEmailEditText(s);
}
});
binding.password.addTextChangedListener(new TextChangedListener<>(binding.password) {
@Override
public void onTextChanged(TextInputEditText target, Editable s) {
listenerPasswordEditText(s);
}
});
binding.btEnter.setOnClickListener(this::onClickListenerLoginButton);
subscribe();
});
}
private void subscribe() {
viewModel.errorLiveData.observe(this, error -> {
binding.btEnter.setEnabled(true);
Snackbar.make(findViewById(android.R.id.content), error, Snackbar.LENGTH_LONG).show();
});
viewModel.openLiveData.observe(this, employee -> {
binding.btEnter.setEnabled(true);
SharedPreferences settings = this.getSharedPreferences(
SettingConstants.PREFS_FILE, Context.MODE_PRIVATE
);
settings.edit().putLong(SettingConstants.PREF_ID, employee.getId()).apply();
settings.edit().putString(SettingConstants.PREF_ROLE, employee.getRole()).apply();
startActivity(new Intent(getApplicationContext(), MainActivity.class));
});
}
private void listenerEmailEditText(Editable s) {
if (s.toString().isEmpty()) {
binding.email.setError("Обязательное поле");
} else if (!isEmailValid(s.toString())) {
binding.emailLay.setError("Неверный формат");
} else {
binding.emailLay.setErrorEnabled(false);
}
}
private void listenerPasswordEditText(Editable s) {
if (s.toString().isEmpty()) {
binding.passwordLay.setError("Обязательное поле");
} else {
binding.passwordLay.setErrorEnabled(false);
}
}
private void onClickListenerLoginButton(View view) {
binding.btEnter.setEnabled(false);
viewModel.changeEmail(String.valueOf(binding.email.getText()));
viewModel.changePassword(String.valueOf(binding.password.getText()));
viewModel.confirm();
}
private boolean isEmailValid(String email) {
return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches();
}
}

@ -1,24 +1,23 @@
package ru.myitschool.work.ui.viewModel; package ru.myitschool.work.ui.login;
import androidx.lifecycle.ViewModel;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import ru.myitschool.work.api.data.SignRepositoryImpl; import ru.myitschool.work.api.data.SignRepositoryImpl;
import ru.myitschool.work.api.domain.entity.employee.EmployeeEntity; import ru.myitschool.work.api.domain.entity.employee.EmpolyeeEntity;
import ru.myitschool.work.api.domain.useCases.sign.LoginEmployeeUseCase; import ru.myitschool.work.api.domain.useCases.sign.LoginEmployeeUseCase;
public class LoginViewModel extends ViewModel { public class LoginViewModel extends ViewModel {
private final MutableLiveData<String> mutableErrorLiveData = new MutableLiveData<>(); private final MutableLiveData<String> mutableErrorLiveData = new MutableLiveData<>();
public final LiveData<String> errorLiveData = mutableErrorLiveData; public final LiveData<String> errorLiveData = mutableErrorLiveData;
private final MutableLiveData<EmployeeEntity> mutableOpenLiveData = new MutableLiveData<>(); private final MutableLiveData<EmpolyeeEntity> mutableOpenLiveData = new MutableLiveData<>();
public final LiveData<EmployeeEntity> openLiveData = mutableOpenLiveData; public final LiveData<EmpolyeeEntity> openLiveData = mutableOpenLiveData;
private final LoginEmployeeUseCase loginVolunteerUseCase = new LoginEmployeeUseCase( private final LoginEmployeeUseCase loginEmployeeUseCase = new LoginEmployeeUseCase(
SignRepositoryImpl.getInstance() SignRepositoryImpl.getInstance()
); );
@ -40,19 +39,19 @@ public class LoginViewModel extends ViewModel {
final String currentPassword = password; final String currentPassword = password;
if (currentEmail == null || currentEmail.isEmpty()) { if (currentEmail == null || currentEmail.isEmpty()) {
mutableErrorLiveData.postValue("email пустой!");
return;
}
if (currentPassword == null || currentPassword.isEmpty()) {
mutableErrorLiveData.postValue("Пароль пустой!"); mutableErrorLiveData.postValue("Пароль пустой!");
return; return;
} }
loginVolunteerUseCase.execute("example1@gmail.com", "password", status -> { if (currentPassword == null || currentPassword.isEmpty()) {
mutableErrorLiveData.postValue("email пустой!");
return;
}
loginEmployeeUseCase.execute(currentEmail, currentPassword, status -> {
if (status.getStatusCode() == 200 && status.getErrors() == null && status.getValue() != null) { if (status.getStatusCode() == 200 && status.getErrors() == null && status.getValue() != null) {
mutableOpenLiveData.postValue(status.getValue()); mutableOpenLiveData.postValue(status.getValue());
} else if (status.getStatusCode() == 401) } else if (status.getStatusCode() == 401) mutableErrorLiveData.postValue("Данные не верны. Попробуйте ещё разок :(");
mutableErrorLiveData.postValue("Данные не верны. Попробуйте ещё разок :("); else mutableErrorLiveData.postValue("Вы не подключены к интернету :(");
else mutableErrorLiveData.postValue("Вы не подключены к интернету :( " + status.getStatusCode() + " " + status.getValue());
}); });
} }
} }

@ -0,0 +1,76 @@
package ru.myitschool.work.ui.main
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment
import com.example.myapplication.core.RoleConstants
import com.example.myapplication.core.SettingConstants
import com.google.android.material.bottomnavigation.BottomNavigationView
import ru.myitschool.work.R
import ru.myitschool.work.ui.createemployee.CreateUserFragment
import ru.myitschool.work.ui.login.LoginActivity
import ru.myitschool.work.ui.profile.ProfileFragment
import ru.myitschool.work.ui.qr.scan.QrScanFragment
import ru.myitschool.work.ui.userlist.CompanyInfoFragment
class MainActivity : AppCompatActivity() {
private lateinit var settings: SharedPreferences
private lateinit var bottomNavigationView: BottomNavigationView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
settings = getSharedPreferences(SettingConstants.PREFS_FILE, Context.MODE_PRIVATE)
if (settings.getLong(SettingConstants.PREF_ID, SettingConstants.ERROR_ID) == SettingConstants.ERROR_ID) {
Log.d("Test", "(MainActivity) Пользователь не зарегистрирован, запускаем регистрацию.")
startActivity(Intent(this, LoginActivity::class.java))
finish()
return
}
window.navigationBarColor = ContextCompat.getColor(this, R.color.teal_200)
bottomNavigationView = findViewById(R.id.bottom_navigation_view)
if (settings.getString(SettingConstants.PREF_ROLE, SettingConstants.DEF_VALUE) == RoleConstants.ROLE_USER) {
val menuItem = bottomNavigationView.menu.getItem(1);
menuItem.setVisible(false)
}
bottomNavigationView.setOnItemSelectedListener{ item ->
// if (item.itemId == bottomNavigationView.selectedItemId) return@setOnItemSelectedListener false
when (item.itemId) {
R.id.scaner -> replaceFragment(QrScanFragment())
R.id.office -> replaceFragment(CompanyInfoFragment())
R.id.createEmployee -> replaceFragment(CreateUserFragment())
//R.id.employees -> replaceFragment(EmployeesListFragment())
R.id.profile -> replaceFragment(ProfileFragment())
}
window.statusBarColor = ContextCompat.getColor(this, R.color.grey)
return@setOnItemSelectedListener true
}
}
private fun replaceFragment(fragment: Fragment) {
supportFragmentManager.beginTransaction().replace(R.id.container, fragment).commit()
}
}

@ -0,0 +1,35 @@
package ru.myitschool.work.ui.profile;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import ru.myitschool.work.R;
/**
* A simple {@link Fragment} subclass.
* Use the {@link ProfileFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class ProfileFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_profile, container, false);
}
}

@ -0,0 +1,38 @@
package ru.myitschool.work.ui.profile;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import ru.myitschool.work.R;
public class RedactProfileFragment extends Fragment {
private RedactProfileViewModel mViewModel;
public static RedactProfileFragment newInstance() {
return new RedactProfileFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_redact_profile, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = new ViewModelProvider(this).get(RedactProfileViewModel.class);
// TODO: Use the ViewModel
}
}

@ -0,0 +1,7 @@
package ru.myitschool.work.ui.profile;
import androidx.lifecycle.ViewModel;
public class RedactProfileViewModel extends ViewModel {
// TODO: Implement the ViewModel
}

@ -0,0 +1,30 @@
package ru.myitschool.work.ui.qr.scan
import android.os.Bundle
import androidx.core.os.bundleOf
import kotlinx.serialization.Serializable
// НЕ ИЗМЕНЯЙТЕ ЭТОТ ФАЙЛ. В ТЕСТАХ ОН БУДЕМ ВОЗВРАЩЁН В ИСХОДНОЕ СОСТОЯНИЕ
@Serializable
data object QrScanDestination {
const val REQUEST_KEY = "qr_result"
private const val KEY_QR_DATA = "key_qr"
fun newInstance(): QrScanFragment {
return QrScanFragment()
}
fun getDataIfExist(bundle: Bundle): String? {
return if (bundle.containsKey(KEY_QR_DATA)) {
bundle.getString(KEY_QR_DATA)
} else {
null
}
}
internal fun packToBundle(data: String): Bundle {
return bundleOf(
KEY_QR_DATA to data
)
}
}

@ -0,0 +1,139 @@
package ru.myitschool.work.ui.qr.scan
import android.os.Bundle
import android.view.View
import androidx.activity.result.contract.ActivityResultContracts
import androidx.camera.core.ImageAnalysis
import androidx.camera.mlkit.vision.MlKitAnalyzer
import androidx.camera.view.LifecycleCameraController
import androidx.camera.view.PreviewView
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.setFragmentResult
import androidx.fragment.app.viewModels
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.google.mlkit.vision.barcode.BarcodeScanner
import com.google.mlkit.vision.barcode.BarcodeScannerOptions
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.common.Barcode
import ru.myitschool.work.R
import ru.myitschool.work.databinding.FragmentQrScanBinding
import ru.myitschool.work.utils.collectWhenStarted
import ru.myitschool.work.utils.visibleOrGone
// НЕ ИЗМЕНЯЙТЕ ЭТОТ ФАЙЛ. В ТЕСТАХ ОН БУДЕМ ВОЗВРАЩЁН В ИСХОДНОЕ СОСТОЯНИЕ
class QrScanFragment : Fragment(R.layout.fragment_qr_scan) {
private var _binding: FragmentQrScanBinding? = null
private val binding: FragmentQrScanBinding get() = _binding!!
private var barcodeScanner: BarcodeScanner? = null
private var isCameraInit: Boolean = false
private val permissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted -> viewModel.onPermissionResult(isGranted) }
private val viewModel: QrScanViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentQrScanBinding.bind(view)
sendResult(bundleOf())
subscribe()
initCallback()
}
private fun initCallback() {
binding.close.setOnClickListener { viewModel.close() }
}
private fun subscribe() {
viewModel.state.collectWhenStarted(this) { state ->
binding.loading.visibleOrGone(state is QrScanViewModel.State.Loading)
binding.viewFinder.visibleOrGone(state is QrScanViewModel.State.Scan)
if (!isCameraInit && state is QrScanViewModel.State.Scan) {
startCamera()
isCameraInit = true
}
}
viewModel.action.collectWhenStarted(this) { action ->
when (action) {
is QrScanViewModel.Action.RequestPermission -> requestPermission(action.permission)
is QrScanViewModel.Action.CloseWithCancel -> {
goBack()
}
is QrScanViewModel.Action.CloseWithResult -> {
sendResult(QrScanDestination.packToBundle(action.result))
goBack()
}
}
}
}
private fun requestPermission(permission: String) {
permissionLauncher.launch(permission)
}
private fun startCamera() {
val context = requireContext()
val cameraController = LifecycleCameraController(context)
val previewView: PreviewView = binding.viewFinder
val executor = ContextCompat.getMainExecutor(context)
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
.build()
val barcodeScanner = BarcodeScanning.getClient(options)
this.barcodeScanner = barcodeScanner
cameraController.setImageAnalysisAnalyzer(
executor,
MlKitAnalyzer(
listOf(barcodeScanner),
ImageAnalysis.COORDINATE_SYSTEM_VIEW_REFERENCED,
executor
) { result ->
result?.getValue(barcodeScanner)?.firstOrNull()?.let { value ->
viewModel.findBarcode(value)
}
}
)
cameraController.bindToLifecycle(this)
previewView.controller = cameraController
}
override fun onDestroyView() {
barcodeScanner?.close()
barcodeScanner = null
_binding = null
super.onDestroyView()
}
private fun goBack() {
findNavControllerOrNull()?.popBackStack()
?: requireActivity().onBackPressedDispatcher.onBackPressed()
}
private fun sendResult(bundle: Bundle) {
setFragmentResult(
QrScanDestination.REQUEST_KEY,
bundle
)
findNavControllerOrNull()
?.previousBackStackEntry
?.savedStateHandle
?.set(QrScanDestination.REQUEST_KEY, bundle)
}
private fun findNavControllerOrNull(): NavController? {
return try {
findNavController()
} catch (_: Throwable) {
null
}
}
}

@ -0,0 +1,93 @@
package ru.myitschool.work.ui.qr.scan
import android.Manifest
import android.app.Application
import android.content.pm.PackageManager
import androidx.core.content.ContextCompat
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.google.mlkit.vision.barcode.common.Barcode
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import ru.myitschool.work.utils.MutablePublishFlow
// НЕ ИЗМЕНЯЙТЕ ЭТОТ ФАЙЛ. В ТЕСТАХ ОН БУДЕМ ВОЗВРАЩЁН В ИСХОДНОЕ СОСТОЯНИЕ
class QrScanViewModel(
application: Application
) : AndroidViewModel(application) {
private val _action = MutablePublishFlow<Action>()
val action = _action.asSharedFlow()
private val _state = MutableStateFlow<State>(initialState)
val state = _state.asStateFlow()
init {
checkPermission()
}
fun onPermissionResult(isGranted: Boolean) {
viewModelScope.launch {
if (isGranted) {
_state.update { State.Scan }
} else {
_action.emit(Action.CloseWithCancel)
}
}
}
private fun checkPermission() {
viewModelScope.launch {
val isPermissionGranted = ContextCompat.checkSelfPermission(
getApplication(),
CAMERA_PERMISSION
) == PackageManager.PERMISSION_GRANTED
if (isPermissionGranted) {
_state.update { State.Scan }
} else {
delay(1000)
_action.emit(Action.RequestPermission(CAMERA_PERMISSION))
}
}
}
fun findBarcode(barcode: Barcode) {
viewModelScope.launch {
barcode.rawValue?.let { value ->
_action.emit(Action.CloseWithResult(value))
}
}
}
fun close() {
viewModelScope.launch {
_action.emit(Action.CloseWithCancel)
}
}
sealed interface State {
data object Loading : State
data object Scan : State
}
sealed interface Action {
data class RequestPermission(
val permission: String
) : Action
data object CloseWithCancel : Action
data class CloseWithResult(
val result: String
) : Action
}
private companion object {
val initialState = State.Loading
const val CAMERA_PERMISSION = Manifest.permission.CAMERA
}
}

@ -1,120 +0,0 @@
package ru.myitschool.work.ui.screens;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import android.widget.Button;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.lifecycle.ViewModelProvider;
import com.example.myapplication.core.SettingConstants;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import ru.myitschool.work.R;
import ru.myitschool.work.ui.viewModel.LoginViewModel;
import ru.myitschool.work.utils.TextChangedListener;
public class LoginActivity extends AppCompatActivity {
private Button loginButton;
private TextInputEditText email;
private TextInputLayout emailLayout;
private TextInputEditText password;
private TextInputLayout passwordLayout;
private LoginViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_login);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
loginButton = findViewById(R.id.loginButton);
email = findViewById(R.id.email);
emailLayout = findViewById(R.id.email_layout);
password = findViewById(R.id.password);
passwordLayout = findViewById(R.id.password_layout);
viewModel = new ViewModelProvider(this).get(LoginViewModel.class);
email.addTextChangedListener(new TextChangedListener<>(email) {
@Override
public void onTextChanged(TextInputEditText target, Editable s) {
listenerEmailEditText(s);
}
});
password.addTextChangedListener(new TextChangedListener<>(password) {
@Override
public void onTextChanged(TextInputEditText target, Editable s) {
listenerPasswordEditText(s);
}
});
loginButton.setOnClickListener(this::onClickListenerLoginButton);
subscribe();
}
private void subscribe() {
viewModel.errorLiveData.observe(this, error -> {
loginButton.setEnabled(true);
Snackbar.make(findViewById(android.R.id.content), error, Snackbar.LENGTH_LONG).show();
});
viewModel.openLiveData.observe(this, employee -> {
loginButton.setEnabled(true);
SharedPreferences settings = getSharedPreferences(
SettingConstants.PREFS_FILE, Context.MODE_PRIVATE
);
settings.edit().putLong(SettingConstants.PREF_ID, employee.getId()).apply();
settings.edit().putString(SettingConstants.PREF_ROLE, employee.getRole()).apply();
startActivity(new Intent(this, MainActivity.class));
finish();
});
}
private void listenerEmailEditText(Editable s) {
if (s.toString().isEmpty()) {
emailLayout.setError("Обязательное поле");
} else if (!isEmailValid(s.toString())) {
emailLayout.setError("Неверный формат");
} else {
emailLayout.setErrorEnabled(false);
}
}
private void listenerPasswordEditText(Editable s) {
if (s.toString().isEmpty()) {
passwordLayout.setError("Обязательное поле");
} else {
passwordLayout.setErrorEnabled(false);
}
}
private void onClickListenerLoginButton(View view) {
loginButton.setEnabled(false);
viewModel.changeEmail(String.valueOf(email.getText()));
viewModel.changePassword(String.valueOf(password.getText()));
viewModel.confirm();
}
private boolean isEmailValid(String email) {
return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches();
}
}

@ -1,40 +0,0 @@
package ru.myitschool.work.ui.screens;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.example.myapplication.core.SettingConstants;
import ru.myitschool.work.R;
public class MainActivity extends AppCompatActivity {
private SharedPreferences settings;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
settings = getSharedPreferences(SettingConstants.PREFS_FILE, MODE_PRIVATE);
if (settings.getLong(SettingConstants.PREF_ID, SettingConstants.ERROR_ID) == SettingConstants.ERROR_ID) {
Log.d("Test", "(MainActivity) Пользователь не авторизован!");
startActivity(new Intent(this, LoginActivity.class));
finish();
}
}
}

@ -1,41 +0,0 @@
package ru.myitschool.work.ui.screens;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import ru.myitschool.work.R;
import ru.myitschool.work.databinding.FragmentQrBinding;
public class QrFragment extends Fragment {
private FragmentQrBinding binding;
public QrFragment() { super(R.layout.fragment_qr); }
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding = FragmentQrBinding.bind(view);
binding.qrButton.setOnClickListener(this::qrScanListener);
}
private void qrScanListener(View view) {
this.requireActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container_view, QrScanFragment.class, null)
.addToBackStack("").commit();
}
@Override
public void onDestroyView() {
binding = null;
super.onDestroyView();
}
}

@ -1,66 +0,0 @@
package ru.myitschool.work.ui.screens;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import ru.myitschool.work.R;
/**
* A simple {@link Fragment} subclass.
* Use the {@link QrScanFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class QrScanFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public QrScanFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment QrScanFragment.
*/
// TODO: Rename and change types and number of parameters
public static QrScanFragment newInstance(String param1, String param2) {
QrScanFragment fragment = new QrScanFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_qr_scan, container, false);
}
}

@ -0,0 +1,38 @@
package ru.myitschool.work.ui.userlist;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import ru.myitschool.work.R;
public class CompanyInfoFragment extends Fragment {
private CompanyInfoViewModel mViewModel;
public static CompanyInfoFragment newInstance() {
return new CompanyInfoFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.company_info_fragment, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = new ViewModelProvider(this).get(CompanyInfoViewModel.class);
// TODO: Use the ViewModel
}
}

@ -0,0 +1,7 @@
package ru.myitschool.work.ui.userlist;
import androidx.lifecycle.ViewModel;
public class CompanyInfoViewModel extends ViewModel {
// TODO: Implement the ViewModel
}

@ -4,7 +4,7 @@ import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
public abstract class TextChangedListener<T> implements TextWatcher { public abstract class TextChangedListener<T> implements TextWatcher {
private final T target; private final T target;
public TextChangedListener(T target) { public TextChangedListener(T target) {
this.target = target; this.target = target;

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/container"
android:layout_width="79dp"
android:layout_height="131dp"
android:layout_above="@+id/bottom_navigation_view"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="0dp" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation_view"
style="@style/Widget.Material3.ActionMode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="0dp"
android:paddingBottom="0dp"
app:itemIconSize="30dp"
app:labelVisibilityMode="unlabeled"
app:menu="@menu/bottom_nav_menu" />
</RelativeLayout>

Binary file not shown.

Before

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 6.1 KiB

Binary file not shown.

After

(image error) Size: 505 B

Binary file not shown.

Before

(image error) Size: 7.0 KiB

Binary file not shown.

Before

(image error) Size: 409 B

After

(image error) Size: 564 B

Binary file not shown.

Before

(image error) Size: 6.7 KiB

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
<!-- The background color, preferably the same as your normal theme -->
<item android:drawable="@color/application_icon_color"/>
<!-- Your product logo - 144dp color version of your app icon -->
<item>
<bitmap
android:src="@drawable/small_application_icon"
android:gravity="center"/>
</item>
</layer-list>

Binary file not shown.

After

(image error) Size: 505 B

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/main_fragment">
<ImageView
android:id="@+id/photo"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:contentDescription="@string/content_description" />
<TextView
android:id="@+id/fullname"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="30dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/photo"
android:gravity="center"
android:textSize="26sp" />
<TextView
android:id="@+id/position"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_below="@+id/fullname"
android:layout_alignParentEnd="true"
android:layout_marginStart="30dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/photo"
android:gravity="center"
android:textSize="26sp" />
<TextView
android:id="@+id/lastEntry"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_below="@+id/position"
android:layout_alignParentEnd="true"
android:layout_marginStart="30dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/photo"
android:gravity="center"
android:textSize="26sp" />
<Button
android:id="@+id/refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/lastEntry"
android:layout_alignParentEnd="true"
android:layout_marginStart="30dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/photo"
android:text="@string/refresh"
android:textSize="26sp" />
<Button
android:id="@+id/logout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/photo"
android:layout_alignEnd="@+id/photo"
android:layout_alignParentStart="true"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:text="@string/logout_text"
android:textSize="26sp" />
<Button
android:id="@+id/scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/logout"
android:layout_alignParentEnd="true"
android:layout_marginStart="30dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/logout"
android:text="@string/scan_text"
android:textSize="26sp" />
<TextView
android:id="@+id/error"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_centerInParent="true"
android:gravity="center"
android:text="@string/error_message_root_activity"
android:textAlignment="center"
android:visibility="gone"
android:padding="5dp"
android:textSize="26sp" />
</RelativeLayout>

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_result"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:screenOrientation="portrait" >
<TextView
android:id="@+id/result"
android:layout_width="570dp"
android:layout_height="305dp"
android:layout_above="@+id/close"
android:layout_centerHorizontal="true"
android:layout_marginBottom="100dp"
android:padding="5dp"
android:textSize="30sp" />
<Button
android:id="@+id/close"
android:layout_width="533dp"
android:layout_height="76dp"
android:layout_centerInParent="true"
android:text="@string/close"
android:textSize="30sp" />
</RelativeLayout>

@ -5,87 +5,93 @@
android:id="@+id/main" android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".ui.screens.LoginActivity" tools:context=".ui.login.LoginActivity"
android:background="@drawable/background_login"> android:background="@drawable/background">
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:layout_width="360dp" android:layout_width="50dp"
android:layout_height="wrap_content" android:layout_height="50dp"
android:layout_centerInParent="true" android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="40dp"
android:layout_marginTop="220dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="270dp"
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="20dp"> app:cardCornerRadius="20dp">
<LinearLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="fill_parent">
android:orientation="vertical"
android:layout_gravity="center_horizontal"
android:padding="24dp">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="104dp"
android:layout_height="wrap_content" android:layout_height="46dp"
android:text="@string/login_text" android:layout_alignParentStart="true"
android:textSize="40sp" android:layout_alignParentTop="true"
android:textAlignment="center" android:layout_alignParentEnd="true"
android:textStyle="bold" /> android:layout_marginStart="115dp"
android:layout_marginTop="40dp"
android:layout_marginEnd="115dp"
android:text="Вход"
android:textColor="@color/black"
android:textSize="40dp" />
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/email_layout" android:id="@+id/email_lay"
android:layout_width="match_parent" android:layout_width="10dp"
android:layout_height="match_parent" android:layout_height="40dp"
app:shapeAppearance="@style/rounded" android:layout_alignParentStart="true"
android:layout_marginTop="20dp" android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
app:boxStrokeColor="@color/login_main_color" android:layout_marginStart="80dp"
app:cursorColor="#49454F" android:layout_marginTop="110dp"
app:hintTextColor="@color/login_main_color"> android:layout_marginEnd="80dp">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/email" android:id="@+id/email"
android:layout_width="match_parent" android:layout_width="fill_parent"
android:layout_height="55dp" android:layout_height="fill_parent"
android:hint="@string/email" android:hint="Email"/>
android:maxLines="1"
android:inputType="text"/>
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/password_layout" android:id="@+id/password_lay"
android:layout_width="match_parent" android:layout_width="10dp"
android:layout_height="match_parent" android:layout_height="40dp"
android:layout_marginTop="5dp" android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
app:shapeAppearance="@style/rounded" android:layout_alignParentEnd="true"
android:layout_marginStart="80dp"
app:endIconMode="password_toggle" android:layout_marginTop="180dp"
app:helperTextTextColor="@color/red" android:layout_marginEnd="80dp">
app:boxStrokeColor="@color/login_main_color"
app:cursorColor="#49454F"
app:hintTextColor="@color/login_main_color">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/password" android:id="@+id/password"
android:layout_width="match_parent" android:layout_width="fill_parent"
android:layout_height="55dp" android:layout_height="fill_parent"
android:hint="@string/password" android:hint="Пароль"/>
android:inputType="textPassword"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<Button <com.google.android.material.button.MaterialButton
android:id="@+id/loginButton" android:id="@+id/bt_enter"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="60dp" android:layout_height="wrap_content"
android:text="@string/login" android:text="Войти в систему"
android:textStyle="bold" android:textColor="@color/white"
android:textSize="16sp" android:layout_alignParentStart="true"
android:layout_marginTop="20dp" android:layout_alignParentTop="true"
android:backgroundTint="@color/login_main_color" android:layout_alignParentEnd="true"
app:cornerRadius="20dp" /> android:layout_marginStart="80dp"
android:layout_marginTop="250dp"
</LinearLayout> android:layout_marginEnd="80dp"
app:backgroundTint="#B1B1CF"/>
</RelativeLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
</RelativeLayout> </RelativeLayout>

@ -1,18 +1,17 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main" android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".ui.screens.MainActivity" android:orientation="horizontal">
android:background="@color/white">
<androidx.fragment.app.FragmentContainerView <androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_view" android:id="@+id/container"
android:layout_width="match_parent" android:layout_width="79dp"
android:layout_height="match_parent" android:layout_height="131dp"
android:name="ru.myitschool.work.ui.screens.QrFragment"
android:layout_above="@+id/bottom_navigation_view" android:layout_above="@+id/bottom_navigation_view"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
@ -20,7 +19,7 @@
android:layout_marginStart="0dp" android:layout_marginStart="0dp"
android:layout_marginTop="0dp" android:layout_marginTop="0dp"
android:layout_marginEnd="0dp" android:layout_marginEnd="0dp"
android:layout_marginBottom="0dp"/> android:layout_marginBottom="0dp" />
<com.google.android.material.bottomnavigation.BottomNavigationView <com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation_view" android:id="@+id/bottom_navigation_view"

@ -0,0 +1,234 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".ui.profile.ProfileFragment">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_user"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"/>
<TextView
android:layout_marginLeft="10dp"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:text="@string/company_info"
android:textSize="25dp"
android:layout_gravity="center"/>
</LinearLayout>
<ImageView
android:id="@+id/imageCompany"
android:layout_width="140dp"
android:layout_height="140dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginTop="90dp"
android:layout_marginEnd="0dp" />
<RelativeLayout
android:id="@+id/relllLay"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_below="@+id/imageCompany"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp">
<TextView
android:id="@+id/nameCompany"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="20dp"
android:layout_marginTop="14dp"
android:layout_marginEnd="38dp"
android:maxLines="1" />
</RelativeLayout>
<com.google.android.material.card.MaterialCardView
android:id="@+id/descriptionLay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/workTimeLay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="10dp"
android:backgroundTint="#B1B1CF"
app:cardCornerRadius="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:background="@drawable/info" />
<TextView
android:id="@+id/description"
android:layout_width="350dp"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="50dp"
android:layout_marginTop="40dp"
android:layout_marginEnd="36dp"
android:layout_marginBottom="10dp"
android:maxLines="10" />
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/description"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="50dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="279dp"
android:text="@string/description" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/workTimeLay"
android:layout_width="wrap_content"
android:layout_height="120dp"
android:layout_below="@+id/relLay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="10dp"
android:backgroundTint="#B1B1CF"
app:cardCornerRadius="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="15dp"
android:layout_marginTop="5dp"
android:background="@drawable/contacts" />
<TextView
android:id="@+id/telephone_tv"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="50dp"
android:layout_marginTop="75dp"
android:layout_marginEnd="36dp"
android:maxLines="1" />
<TextView
android:id="@+id/email_tv"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_below="@+id/telephone_tv"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="50dp"
android:layout_marginTop="40dp"
android:layout_marginEnd="36dp"
android:maxLines="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/telephone_tv"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="50dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="270dp"
android:text="@string/contacts" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/relLay"
android:layout_width="wrap_content"
android:layout_height="80dp"
android:layout_below="@+id/relllLay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="10dp"
android:backgroundTint="#B1B1CF"
app:cardCornerRadius="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="5dp"
android:layout_marginTop="15dp"
android:background="@drawable/ic_address" />
<TextView
android:id="@+id/address"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="50dp"
android:layout_marginTop="37dp"
android:layout_marginEnd="36dp"
android:maxLines="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/address"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="50dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="301dp"
android:text="@string/address" />
</com.google.android.material.card.MaterialCardView>
</RelativeLayout>
</FrameLayout>

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="@+id/search_lay"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_user"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"/>
<androidx.appcompat.widget.SearchView
android:id="@+id/search"
android:layout_width="340dp"
android:layout_marginStart="5dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginEnd="0dp" />
</LinearLayout>
<ScrollView
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_below="@+id/search_lay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</ScrollView>
</RelativeLayout>
</FrameLayout>

@ -0,0 +1,248 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".ui.createemployee.CreateUserFragment"
android:background="@drawable/background">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:orientation="horizontal"
android:background="@color/white">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"
android:background="@drawable/ic_user" />
<TextView
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:text="@string/addEmployee"
android:textSize="25dp" />
</LinearLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/name_create_lay"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginTop="119dp"
android:layout_marginEnd="70dp"
app:shapeAppearance="@style/rounded">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/name_create"
android:layout_width="match_parent"
android:layout_height="40dp"
android:hint="Имя"
android:background="#FFFFFF" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/surname_create_lay"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_below="@+id/name_create_lay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="70dp"
app:shapeAppearance="@style/rounded">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/surname_create"
android:layout_width="match_parent"
android:layout_height="40dp"
android:hint="Фамилия"
android:background="#FFFFFF"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/patronomic_create_lay"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_below="@+id/surname_create_lay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="70dp"
app:shapeAppearance="@style/rounded">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/patronomic_create"
android:layout_width="match_parent"
android:layout_height="40dp"
android:hint="Отчество"
android:background="#FFFFFF"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/telephone_create_lay"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_below="@+id/patronomic_create_lay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="70dp"
app:shapeAppearance="@style/rounded">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/telephone_create"
android:layout_width="match_parent"
android:layout_height="40dp"
android:hint="Телефон"
android:background="#FFFFFF"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/email_create_lay"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_below="@+id/telephone_create_lay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="70dp"
app:shapeAppearance="@style/rounded">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/email_create"
android:layout_width="match_parent"
android:layout_height="40dp"
android:hint="Электронная почта"
android:background="#FFFFFF"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/password_create_lay"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_below="@+id/email_create_lay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="70dp"
app:shapeAppearance="@style/rounded">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password_create"
android:layout_width="match_parent"
android:layout_height="40dp"
android:hint="Пароль"
android:background="#FFFFFF"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/officename_create_lay"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_below="@+id/password_create_lay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="70dp"
app:shapeAppearance="@style/rounded">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/officename_create"
android:layout_width="match_parent"
android:layout_height="40dp"
android:hint="Название офиса"
android:background="#FFFFFF"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/possition_create_lay"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_below="@+id/officename_create_lay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="70dp"
app:shapeAppearance="@style/rounded">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/position_create"
android:layout_width="match_parent"
android:layout_height="40dp"
android:hint="Должность"
android:background="#FFFFFF"/>
</com.google.android.material.textfield.TextInputLayout>
<Spinner
android:id="@+id/role_create_lay"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_below="@+id/possition_create_lay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="70dp"
android:background="@color/white"
android:entries="@array/roles"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/button_create_lay"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_below="@+id/role_create_lay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="70dp"
android:layout_marginTop="40dp"
android:layout_marginEnd="70dp"
android:text="Создать"
android:backgroundTint="#B1CFBB"
android:textColor="@color/black"
app:shapeAppearance="@style/rounded"/>
</RelativeLayout>
</FrameLayout>

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/main_fragment">
<ImageView
android:id="@+id/photo"
android:layout_width="160dp"
android:layout_height="160dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:contentDescription="@string/content_description" />
<TextView
android:id="@+id/fullname"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="30dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/photo"
android:gravity="center" />
<TextView
android:id="@+id/position"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/fullname"
android:layout_alignParentEnd="true"
android:layout_marginStart="30dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/photo"
android:gravity="center" />
<TextView
android:id="@+id/lastEntry"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/position"
android:layout_alignParentEnd="true"
android:layout_marginStart="30dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/photo"
android:gravity="center" />
<Button
android:id="@+id/refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/lastEntry"
android:layout_alignParentEnd="true"
android:layout_marginStart="30dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/photo"
android:text="@string/refresh" />
<Button
android:id="@+id/logout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/photo"
android:layout_alignEnd="@+id/photo"
android:layout_alignParentStart="true"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:text="@string/logout_text" />
<Button
android:id="@+id/scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/logout"
android:layout_alignParentEnd="true"
android:layout_marginStart="30dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/logout"
android:text="@string/scan_text" />
<TextView
android:id="@+id/error"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_centerInParent="true"
android:gravity="center"
android:text="@string/error_message_root_activity"
android:textAlignment="center"
android:visibility="gone"
android:padding="5dp" />
</RelativeLayout>

@ -0,0 +1,224 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".ui.profile.ProfileFragment">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_user"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"/>
<TextView
android:layout_marginLeft="10dp"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:text="@string/info"
android:textSize="25dp"
android:layout_gravity="center"/>
</LinearLayout>
<ImageView
android:id="@+id/imageView2"
android:layout_width="140dp"
android:layout_height="140dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="140dp"
android:layout_marginTop="90dp"
android:layout_marginEnd="140dp" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginTop="265dp"
android:layout_marginEnd="0dp"
android:orientation="horizontal"
android:padding="8dp">
<com.google.android.material.button.MaterialButton
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:text="@string/redact"
android:textColor="@color/black"
app:backgroundTint="@color/white"
app:cornerRadius="30dp"
app:strokeColor="@color/design_default_color_on_primary" />
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginLeft="30dp"
android:text="@string/bloked"
app:backgroundTint="#D46A6C" />
</LinearLayout>
<RelativeLayout
android:id="@+id/relLay"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_below="@+id/linearLayout"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp">
<TextView
android:id="@+id/fio"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="22dp"
android:layout_marginEnd="33dp"
android:maxLines="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/fio"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="300dp"
android:text="@string/FIO"/>
<TextView
android:id="@+id/role"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_below="@+id/fio"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="33dp"
android:maxLines="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/role"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="300dp"
android:text="@string/role"/>
<TextView
android:id="@+id/id_user"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_below="@+id/role"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="33dp"
android:maxLines="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/id_user"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="300dp"
android:text="@string/id"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_below="@+id/relLay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp">
<TextView
android:id="@+id/telephone"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="22dp"
android:layout_marginEnd="33dp"
android:maxLines="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/telephone"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="300dp"
android:text="@string/phoneNum"/>
<TextView
android:id="@+id/email"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_below="@+id/telephone"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="33dp"
android:maxLines="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/email"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="230dp"
android:text="@string/email"/>
</RelativeLayout>
</RelativeLayout>
</FrameLayout>

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".ui.screens.QrFragment"
android:background="@drawable/background_qr_fragment">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/session_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="50dp"
android:text="@string/session_30_days"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="24sp" />
<TextView
android:id="@+id/session_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="90dp"
android:text="@string/hours_500"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="22sp" />
<ImageButton
android:id="@+id/qr_button"
android:layout_width="180dp"
android:layout_height="180dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="176dp"
android:contentDescription="@string/qr_code"
android:src="@drawable/qr_code"
android:background="#1E1F5C"/>
</RelativeLayout>
</FrameLayout>

@ -1,22 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
tools:context=".ui.screens.QrScanFragment">
<RelativeLayout <androidx.camera.view.PreviewView
android:layout_width="match_parent" android:id="@+id/viewFinder"
android:layout_height="match_parent"> android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView <com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="match_parent" android:id="@+id/close"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:layout_centerInParent="true" android:layout_height="wrap_content"
android:text="Сканирование qr кода" android:layout_margin="16dp"
android:textAlignment="center" android:contentDescription="@string/close_button"
android:textSize="30sp" /> android:src="@drawable/ic_close"
app:elevation="0dp"
</RelativeLayout> app:layout_constraintStart_toStartOf="parent"
</FrameLayout> app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,217 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".ui.profile.ProfileFragment">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_user"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"/>
<TextView
android:layout_marginLeft="10dp"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:text="@string/setProfile"
android:textSize="25dp"
android:layout_gravity="center"/>
</LinearLayout>
<ImageView
android:id="@+id/profile_image_view"
android:layout_width="140dp"
android:layout_height="140dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="140dp"
android:layout_marginTop="90dp"
android:layout_marginEnd="140dp"
android:background="@color/black" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginTop="265dp"
android:layout_marginEnd="0dp"
android:orientation="horizontal"
android:padding="8dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/changeProfile"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="100dp"
android:text="@string/redacting"
android:textColor="@color/black"
android:textSize="10dp"
app:backgroundTint="@color/white" />
</LinearLayout>
<RelativeLayout
android:id="@+id/relLay"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_below="@+id/linearLayout"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp">
<EditText
android:id="@+id/fio_et"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="22dp"
android:layout_marginEnd="33dp"
android:maxLines="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/fio_et"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="300dp"
android:text="@string/FIO"/>
<EditText
android:id="@+id/role_et"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_below="@+id/fio_et"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="33dp"
android:maxLines="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/role_et"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="300dp"
android:text="@string/role"/>
<EditText
android:id="@+id/id_user_et"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_below="@+id/role_et"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="33dp"
android:maxLines="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/id_user_et"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="300dp"
android:text="@string/id"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_below="@+id/relLay"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp">
<EditText
android:id="@+id/telephone_et"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="22dp"
android:layout_marginEnd="33dp"
android:maxLines="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/telephone_et"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="300dp"
android:text="@string/phoneNum"/>
<EditText
android:id="@+id/email_et"
android:layout_width="350dp"
android:layout_height="30dp"
android:layout_below="@+id/telephone_et"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="33dp"
android:maxLines="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/email_et"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="32dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="230dp"
android:text="@string/email"/>
</RelativeLayout>
</RelativeLayout>
</FrameLayout>

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment_result"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/result"
android:layout_width="180dp"
android:layout_height="80dp"
android:layout_above="@+id/close"
android:layout_centerHorizontal="true"
android:layout_marginBottom="100dp"
android:padding="5dp" />
<Button
android:id="@+id/close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/close" />
</RelativeLayout>

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="120dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardElevation="4dp"
app:cardBackgroundColor="#B1B1CF"
app:cardCornerRadius="15dp"
android:layout_margin="10dp">
<View
android:layout_width="8dp"
android:layout_height="120dp"
android:layout_marginLeft="265dp"
android:layout_marginRight="-5dp"
android:background="#B1CFBB"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/profile_image"
style="@style/Circle"
android:background="@color/black"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:layout_marginStart="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="30dp"
android:maxLines="1"
android:layout_marginTop="10dp"
android:textColor="@color/black"/>
<TextView
android:id="@+id/user_id"
android:layout_width="match_parent"
android:layout_height="25dp"
android:maxLines="1"
android:layout_marginTop="10dp"
android:textColor="#D9D9D9"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="16dp"
android:orientation="vertical"
android:layout_gravity="right">
<TextView
android:id="@+id/sessionText"
android:layout_width="match_parent"
android:layout_height="30dp"
android:maxLines="1"
android:layout_marginTop="10dp"
android:textColor="@color/black"
android:text="Текущая сессия"/>
<TextView
android:id="@+id/dateAndTimeSession"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_marginTop="10dp"
android:textColor="@color/black"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

@ -15,6 +15,13 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<item
android:id="@+id/createEmployee"
android:title="@string/createEmployee"
android:icon="@drawable/ic_create_employee"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<item <item
android:id="@+id/employees" android:id="@+id/employees"
android:title="@string/employees" android:title="@string/employees"

@ -7,11 +7,5 @@
<color name="teal_700">#FF018786</color> <color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<color name="grey">#11FFFFFF</color>
<color name="black_overlay">#66000000</color>
<color name="application_icon_color">#040827</color>
<color name="login_main_color">#B1B1CF</color>
<color name="green">#678B78</color>
<color name="red">#FF0000</color>
</resources> </resources>

@ -1,5 +1,5 @@
<resources> <resources>
<string name="app_name">QRP</string> <string name="app_name">NTO Client 2024</string>
<!-- Всё, что относится к LoginActivity --> <!-- Всё, что относится к LoginActivity -->
<string name="title_activity_login">LoginActivity</string> <string name="title_activity_login">LoginActivity</string>
@ -23,7 +23,7 @@
<string name="profile">Профиль</string> <string name="profile">Профиль</string>
<string name="office">Офис</string> <string name="office">Офис</string>
<string name="scaning">Сканировать</string> <string name="scaning">Сканировать</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string> <string name="hello_blank_fragment">Hello blank fragment</string>
<string name="info">Информация о сотруднике</string> <string name="info">Информация о сотруднике</string>
<string name="redact">Редактировать</string> <string name="redact">Редактировать</string>
@ -39,10 +39,11 @@
<string name="address">Адрес</string> <string name="address">Адрес</string>
<string name="contacts">Контакты</string> <string name="contacts">Контакты</string>
<string name="description">Описание</string> <string name="description">Описание</string>
<string name="login">Войти</string> <string name="createEmployee">Создать сотрудника</string>
<string name="password">Пароль</string> <string name="addEmployee">Добавить сотрудника</string>
<string name="login_text">Вход</string>
<string name="qr_code">qr_code</string> <string-array name="roles">
<string name="hours_500">500 часов</string> <item>Админ</item>
<string name="session_30_days">Сессии за последние 30 дней:</string> <item>Пользователь</item>
</string-array>
</resources> </resources>

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<style name="Widget.Theme.MyApplication.ButtonBar.Fullscreen" parent=""> <style name="Widget.Theme.MyApplication.ButtonBar.Fullscreen" parent="">
<item name="android:background">@color/black_overlay</item> <item name="android:background">@color/black</item>
<item name="android:buttonBarStyle">?android:attr/buttonBarStyle</item> <item name="android:buttonBarStyle">?android:attr/buttonBarStyle</item>
</style> </style>
@ -22,10 +23,6 @@
<item name="cornerSize">6dp</item> <item name="cornerSize">6dp</item>
</style> </style>
<style name="splashScreenTheme" parent="@style/AppTheme.NoActionBar">
<item name="android:windowBackground">@drawable/splash_screen</item>
</style>
<style name="circleImageView" parent=""> <style name="circleImageView" parent="">
<item name="cornerFamily">rounded</item> <item name="cornerFamily">rounded</item>
<item name="cornerSize">50%</item> <item name="cornerSize">50%</item>

@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="AppTheme.NoActionBar" parent="Theme.Material3.DayNight.NoActionBar"> <style name="Theme.Default" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item> <item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorPrimaryVariant">@color/purple_700</item>