extends VBoxContainer const TimeSlot = preload("res://scenes/board/time_slot.tscn") const ReservationScene = preload("res://scenes/board/reservation.tscn") const WorkingDayStart = 8 const WorkingDayEnd = 20 const MinimalMinutesToShowTitle = 30 const MinimalMinutesForBigSize = 60 const DateUpdateInterval := 60.0 const ScheduleUpdateInterval := 1.0 # 5.0 @onready var _main: Main = get_tree().get_current_scene() @onready var _timeline = $Panel/Timeline @onready var _reservations = $Panel/Reservations @onready var _date = $TopBar/DateButton @onready var _room = $TopBar/RoomButton @onready var _rooms_menu = $RoomsMenu var _date_update_timer := 0.0 var _schedule_update_timer := 0.0 var _blocked_after_loading := false var _block_reservation_creation := false var _rooms : Array[RoomEntity] = [] var _reservations_list : Array[ReservationEntity] = [] func _process(delta): _process_hour_size() _process_date(delta) _process_fonts() _process_schedule(delta) func _process_hour_size(): var hour_size = get_viewport_rect().size.y/15 for time_slot in _timeline.get_children(): time_slot.set_height(hour_size) func _process_date(delta): _date_update_timer += delta if _date_update_timer >= DateUpdateInterval: update_date() _date_update_timer = 0.0 func update_date(): _date.text = _main.get_selected_date() func _process_fonts(): _process_font_size(_date, 35) _process_font_size(_room, 35) func _process_font_size(obj, k): var font_size = obj.get_theme_default_font_size() var new_font_size = get_viewport_rect().size.y/k if font_size != new_font_size: obj.add_theme_font_size_override("font_size", new_font_size) func _process_schedule(delta): if _schedule_update_timer >= ScheduleUpdateInterval: _schedule_update_timer = 0.0 _update_schedule() _schedule_update_timer += delta func _ready(): _remove_reservations() _initialize() func _initialize(): _connect_signals() _remove_time_slots() _fill_with_slots() await get_tree().create_timer(0.1, false).timeout _load_rooms() update_date() func _connect_signals(): await _main.ready var event_handler = _main.get_event_handler() event_handler.reservations_updated.connect(_on_reservations_updated) _room.pressed.connect(_on_room_button_pressed) _rooms_menu.item_clicked.connect(_on_room_selected) _date.pressed.connect(_on_date_button_pressed) func _remove_time_slots(): for time_slot in _timeline.get_children(): time_slot.queue_free() func _fill_with_slots(): for hour in range(WorkingDayStart, WorkingDayEnd): var slot = TimeSlot.instantiate() _timeline.add_child(slot) slot.set_time(hour) func _remove_reservations(): for reservation in _reservations.get_children(): reservation.queue_free() func _load_rooms(): var room_repo = _main.get_room_repo() if room_repo.get_selected_room(): return _rooms_menu.clear() var rooms = await room_repo.list_rooms() for room in rooms: _rooms.append(room) _rooms_menu.add_item(room.title) if len(rooms) < 0: print('Not enough rooms') _rooms_menu.select(0) _on_room_selected(0, '') func _update_schedule(reservations=null): if not _main.is_node_ready(): await _main.ready var reservation_repo = _main.get_reservation_repo() if reservations == null: var room = _main.get_selected_room() reservations = await reservation_repo.list_reservations({ "date": _main.get_selected_date(), "room_id": room.id if room else '' }) if reservations_are_updated(reservations): return _reservations_list = reservations _remove_reservations() for reservation in reservations: var start_time_hours = reservation.start_time.hours var start_time_minutes = reservation.start_time.minutes var start_time = (start_time_hours - WorkingDayStart)*60 + start_time_minutes var finish_time_hours = reservation.finish_time.hours var finish_time_minutes = reservation.finish_time.minutes var finish_time = (finish_time_hours - WorkingDayStart)*60 + finish_time_minutes var reservation_time = finish_time - start_time _compose_reservation(start_time, reservation_time, \ reservation.title, reservation.color, reservation.id) func reservations_are_updated(new_reservations: Array[ReservationEntity]) -> bool: if _reservations_list.size() == 0: return false if _reservations_list.size() != new_reservations.size(): return false for i in range(_reservations_list.size()): var entity_a = _reservations_list[i] var entity_b = new_reservations[i] if !(entity_a is ReservationEntity) || !(entity_b is ReservationEntity): return false if !entity_a.is_identical(entity_b): return false return true func _compose_reservation(start_time, duration_time, title, color, id): if duration_time < MinimalMinutesToShowTitle: title = "" var reservation = ReservationScene.instantiate() _reservations.add_child(reservation) reservation.set_start_time(start_time) reservation.set_duration_time(duration_time) reservation.set_title(title) reservation.set_color(color) reservation.set_id(id) if duration_time < MinimalMinutesForBigSize: reservation.set_font(reservation.Fonts.MEDIUM) func _input(event): if _blocked_after_loading or not _main.get_current_page() == Main.Pages.Board: return if event is InputEventScreenTouch or (event is InputEventMouseButton and event.pressed): if _clicked_on_timeline(event.position): await get_tree().create_timer(0.01, false).timeout if _block_reservation_creation: _block_reservation_creation = false return if _main.get_current_page() == Main.Pages.Board: var time = _get_time_by_position(event.position) if _time_is_before_current_time(time) and _selected_date_is_current(): return var creation_page = _main.load_page(Main.Pages.ReservationCreation) creation_page.clean() creation_page.update() creation_page.set_start_time(time) func _get_time_by_position(position): var hour_size = get_viewport_rect().size.y / 15 var hours_with_minutes_in_float = \ (position.y - _timeline.global_position.y) / hour_size + WorkingDayStart var hours = floor(hours_with_minutes_in_float) var minutes = (hours_with_minutes_in_float - hours) * 60 var minutes_normalized = floor(minutes/30)*30 return {"hours": hours, "minutes": minutes_normalized} func _clicked_on_timeline(pos: Vector2): var timeline_position = _timeline.global_position return ( pos.x > timeline_position.x and pos.x < _timeline.size.x + timeline_position.x ) and ( pos.y > timeline_position.y and pos.y < _timeline.size.y + timeline_position.y ) func _selected_date_is_current(): return _main.get_selected_date() == _main.get_current_date() func _time_is_before_current_time(time): var current_time = Time.get_time_dict_from_system() var time_in_minutes = time.hours*60 + time.minutes var current_time_in_minutes = current_time.hour*60 + current_time.minute return time_in_minutes < current_time_in_minutes func _block_board_click_for(seconds: float): _blocked_after_loading = true await get_tree().create_timer(seconds, false).timeout _blocked_after_loading = false func _on_room_button_pressed(): if _rooms_menu.visible: _rooms_menu.hide() else: _rooms_menu.show() func _on_room_selected(idx, text): var room_repo = _main.get_room_repo() room_repo.set_selected_room(_rooms[idx]) _block_reservation_creation = true _room.text = _rooms[idx].title _rooms_menu.hide() update() func _on_date_button_pressed(): _main.start_date_selection() _main.load_page(Main.Pages.CalendarSetting) func _on_reservations_updated(reservations): await get_tree().create_timer(0.1, false).timeout update() func update(): _block_board_click_for(0.25) _initialize() _update_schedule()