From deb18f48c06230cbee7e6389a24489af9511357b Mon Sep 17 00:00:00 2001 From: kashiuno Date: Tue, 18 Feb 2025 22:29:33 +0300 Subject: [PATCH] Add rent functions --- .../qr_access_admin/common/MainLayout.java | 2 + .../partner/component/PartnerEditor.java | 4 +- .../rent/component/RentEditor.java | 107 ++++++++++++++++++ .../rent/entity/RentEntity.java | 46 ++++++++ .../rent/entity/RentRepository.java | 8 ++ .../qr_access_admin/rent/view/RentView.java | 80 +++++++++++++ 6 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 src/main/java/ru/vyatsu/qr_access_admin/rent/component/RentEditor.java create mode 100644 src/main/java/ru/vyatsu/qr_access_admin/rent/entity/RentEntity.java create mode 100644 src/main/java/ru/vyatsu/qr_access_admin/rent/entity/RentRepository.java create mode 100644 src/main/java/ru/vyatsu/qr_access_admin/rent/view/RentView.java diff --git a/src/main/java/ru/vyatsu/qr_access_admin/common/MainLayout.java b/src/main/java/ru/vyatsu/qr_access_admin/common/MainLayout.java index 6dba745..feb1657 100644 --- a/src/main/java/ru/vyatsu/qr_access_admin/common/MainLayout.java +++ b/src/main/java/ru/vyatsu/qr_access_admin/common/MainLayout.java @@ -19,6 +19,7 @@ import ru.vyatsu.qr_access_admin.client.view.ClientView; import ru.vyatsu.qr_access_admin.common.view.MainView; import ru.vyatsu.qr_access_admin.door.view.DoorView; import ru.vyatsu.qr_access_admin.partner.view.PartnerView; +import ru.vyatsu.qr_access_admin.rent.view.RentView; import ru.vyatsu.qr_access_admin.unit.view.UnitView; import java.util.Optional; @@ -120,6 +121,7 @@ public class MainLayout extends AppLayout { createTab("Устройства", UnitView.class), createTab("Двери", DoorView.class), createTab("Партнеры", PartnerView.class), + createTab("Бронирование", RentView.class), createTab("Клиенты", ClientView.class) }; } diff --git a/src/main/java/ru/vyatsu/qr_access_admin/partner/component/PartnerEditor.java b/src/main/java/ru/vyatsu/qr_access_admin/partner/component/PartnerEditor.java index 5150d81..9b272d8 100644 --- a/src/main/java/ru/vyatsu/qr_access_admin/partner/component/PartnerEditor.java +++ b/src/main/java/ru/vyatsu/qr_access_admin/partner/component/PartnerEditor.java @@ -17,11 +17,11 @@ import ru.vyatsu.qr_access_admin.partner.entity.PartnerEntity; public class PartnerEditor extends Composite { public interface SaveListener { - void onSave(PartnerEntity qr); + void onSave(PartnerEntity partner); } public interface DeleteListener { - void onDelete(PartnerEntity qr); + void onDelete(PartnerEntity partner); } public interface CancelListener { diff --git a/src/main/java/ru/vyatsu/qr_access_admin/rent/component/RentEditor.java b/src/main/java/ru/vyatsu/qr_access_admin/rent/component/RentEditor.java new file mode 100644 index 0000000..c981be1 --- /dev/null +++ b/src/main/java/ru/vyatsu/qr_access_admin/rent/component/RentEditor.java @@ -0,0 +1,107 @@ +package ru.vyatsu.qr_access_admin.rent.component; + +import com.vaadin.flow.component.Composite; +import com.vaadin.flow.component.Key; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.button.ButtonVariant; +import com.vaadin.flow.component.checkbox.Checkbox; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.datepicker.DatePicker; +import com.vaadin.flow.component.icon.VaadinIcon; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.component.timepicker.TimePicker; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.Binder; +import lombok.Getter; +import lombok.Setter; +import ru.vyatsu.qr_access_admin.client.entity.ClientEntity; +import ru.vyatsu.qr_access_admin.client.entity.ClientRepository; +import ru.vyatsu.qr_access_admin.door.entity.DoorEntity; +import ru.vyatsu.qr_access_admin.door.entity.DoorRepository; +import ru.vyatsu.qr_access_admin.rent.entity.RentEntity; + +import java.util.Map; +import java.util.stream.Collectors; + +public class RentEditor extends Composite { + + public interface SaveListener { + void onSave(RentEntity rent); + } + + public interface DeleteListener { + void onDelete(RentEntity rent); + } + + public interface CancelListener { + void onCancel(); + } + + private volatile RentEntity currentRent; + + @Getter + @Setter + private SaveListener saveListener; + @Getter + @Setter + private DeleteListener deleteListener; + @Getter + @Setter + private CancelListener cancelListener; + + private final Binder binder = new BeanValidationBinder<>(RentEntity.class); + + public void setCurrentRent(RentEntity rent) { + this.currentRent = rent; + binder.setBean(rent); + } + + public RentEditor(DoorRepository doorRepository, ClientRepository clientRepository) { + var startTimeField = new TimePicker("Время начала действия"); + var endTimeField = new TimePicker("Время окончания действия"); + var dateField = new DatePicker("Дата бронирования"); + var qrCodeField = new TextField("Закодированный идентификатор"); + var payedField = new Checkbox("Оплачено"); + ComboBox doorField = new ComboBox<>("Дверь"); + doorField.setItemLabelGenerator(DoorEntity::getDescription); + ComboBox clientField = new ComboBox<>("Клиент"); + clientField.setItemLabelGenerator(ClientEntity::getEmail); + Map doors = doorRepository.findAllByParentDoorIdsIsNull() + .stream() + .collect(Collectors.toMap(DoorEntity::getId, d -> d)); + Map clients = clientRepository.findAll() + .stream() + .collect(Collectors.toMap(ClientEntity::getId, c -> c)); + doorField.setItems(doors.values()); + clientField.setItems(clients.values()); + + binder.forField(doorField) + .withConverter(DoorEntity::getId, doors::get) + .bind("doorId"); + binder.forField(clientField) + .withConverter(ClientEntity::getId, clients::get) + .bind("clientId"); + binder.forField(startTimeField).bind("startTime"); + binder.forField(endTimeField).bind("endTime"); + binder.forField(dateField).bind("date"); + binder.forField(qrCodeField).bind("qrCode"); + binder.forField(payedField).bind("payed"); + + var save = new Button("Сохранить", VaadinIcon.CHECK.create()); + var cancel = new Button("Отмена"); + var delete = new Button("Удалить", VaadinIcon.TRASH.create()); + + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + save.addClickListener(e -> saveListener.onSave(currentRent)); + save.addClickShortcut(Key.ENTER); + + delete.addThemeVariants(ButtonVariant.LUMO_ERROR); + delete.addClickListener(e -> deleteListener.onDelete(currentRent)); + + cancel.addClickListener(e -> cancelListener.onCancel()); + + getContent().add(startTimeField, endTimeField, dateField, doorField, clientField, qrCodeField, payedField, new HorizontalLayout(save, cancel, delete)); + } +} diff --git a/src/main/java/ru/vyatsu/qr_access_admin/rent/entity/RentEntity.java b/src/main/java/ru/vyatsu/qr_access_admin/rent/entity/RentEntity.java new file mode 100644 index 0000000..7e56cb9 --- /dev/null +++ b/src/main/java/ru/vyatsu/qr_access_admin/rent/entity/RentEntity.java @@ -0,0 +1,46 @@ +package ru.vyatsu.qr_access_admin.rent.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.SourceType; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; + +@Table(name = "rent") +@Entity +@Getter +@Setter +public class RentEntity { + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private String id; + + @Column + private LocalTime startTime; + + @Column + private LocalTime endTime; + + @Column + private String clientId; + + @Column + private LocalDate date; + + @Column + private String doorId; + + @Column + private String qrCode; + + @Column + private Boolean payed; + + @Column + @CreationTimestamp(source = SourceType.DB) + private LocalDateTime dateCreated; +} diff --git a/src/main/java/ru/vyatsu/qr_access_admin/rent/entity/RentRepository.java b/src/main/java/ru/vyatsu/qr_access_admin/rent/entity/RentRepository.java new file mode 100644 index 0000000..f4b1369 --- /dev/null +++ b/src/main/java/ru/vyatsu/qr_access_admin/rent/entity/RentRepository.java @@ -0,0 +1,8 @@ +package ru.vyatsu.qr_access_admin.rent.entity; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface RentRepository extends JpaRepository { +} diff --git a/src/main/java/ru/vyatsu/qr_access_admin/rent/view/RentView.java b/src/main/java/ru/vyatsu/qr_access_admin/rent/view/RentView.java new file mode 100644 index 0000000..c5abadd --- /dev/null +++ b/src/main/java/ru/vyatsu/qr_access_admin/rent/view/RentView.java @@ -0,0 +1,80 @@ +package ru.vyatsu.qr_access_admin.rent.view; + +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.icon.VaadinIcon; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import jakarta.annotation.security.PermitAll; +import ru.vyatsu.qr_access_admin.client.entity.ClientRepository; +import ru.vyatsu.qr_access_admin.common.MainLayout; +import ru.vyatsu.qr_access_admin.door.entity.DoorRepository; +import ru.vyatsu.qr_access_admin.rent.component.RentEditor; +import ru.vyatsu.qr_access_admin.rent.entity.RentEntity; +import ru.vyatsu.qr_access_admin.rent.entity.RentRepository; + +import java.util.List; + +@Route(value = "rent", layout = MainLayout.class) +@PageTitle("Бронирование") +@PermitAll +public class RentView extends VerticalLayout { + private final RentRepository repository; + private final Grid grid; + private final RentEditor editor; + + public RentView(RentRepository repository, DoorRepository doorRepository, ClientRepository clientRepository) { + this.repository = repository; + + var addButton = new Button("Добавить бронирование", VaadinIcon.PLUS.create()); + grid = new Grid<>(RentEntity.class); + grid.setColumns("clientId", "date", "startTime", "endTime", "payed", "dateCreated"); + editor = new RentEditor(doorRepository, clientRepository); + + var actionsLayout = new HorizontalLayout(addButton); + add(actionsLayout, grid, editor); + + this.configureEditor(); + + addButton.addClickListener(e -> editRent(new RentEntity())); + + grid.setHeight("200px"); + grid.asSingleSelect().addValueChangeListener(e -> editRent(e.getValue())); + + refreshRentGrid(); + } + + private void refreshRentGrid() { + List entities = repository.findAll(); + grid.setItems(entities); + } + + private void editRent(RentEntity rent) { + if (rent == null) { + editor.setVisible(false); + } else { + editor.setVisible(true); + editor.setCurrentRent(rent); + } + } + + private void configureEditor() { + editor.setVisible(false); + + editor.setSaveListener(rent -> { + repository.save(rent); + refreshRentGrid(); + editRent(null); + }); + + editor.setDeleteListener(rent -> { + repository.deleteById(rent.getId()); + refreshRentGrid(); + editRent(null); + }); + + editor.setCancelListener(() -> editRent(null)); + } +}