commit e11999eef5b19d22ea632070a5429a97fce11eed Author: DarkSlein Date: Wed Jan 29 00:45:44 2025 +0300 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2014a87 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Godot 4+ specific ignores +.godot/ +addons/ \ No newline at end of file diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md new file mode 100644 index 0000000..0d4b741 --- /dev/null +++ b/ATTRIBUTION.md @@ -0,0 +1,36 @@ +# Attribution +## Collaborators + +### Role +Person 1 +Person 2 +[Person w/ Link]() + + +## Sourced / Unaffiliated +### Asset Type +#### Use Case +Author: [Name]() +Source: [Domain : webpage.html]() +License: [License]() + +#### Godot Engine Logo +Author: Andrea Calabró +Source: [godotengine.org : press](https://godotengine.org/press/) +License: [CC BY 4.0 International](https://github.com/godotengine/godot/blob/master/LOGO_LICENSE.txt) + +## Tools +#### Godot +Author: [Juan Linietsky, Ariel Manzur, and contributors](https://godotengine.org/contact) +Source: [godotengine.org](https://godotengine.org/) +License: [MIT License](https://github.com/godotengine/godot/blob/master/LICENSE.txt) + +#### Git +Author: [Linus Torvalds](https://github.com/torvalds) +Source: [git-scm.com](https://git-scm.com/downloads) +License: [GNU General Public License version 2](https://opensource.org/licenses/GPL-2.0) + +#### Godot Menus Template +Author: [Marek Belski](https://github.com/Maaack/Godot-Menus-Template/graphs/contributors) +Source: [github: Godot-Menus-Template](https://github.com/Maaack/Godot-Menus-Template) +License: [MIT License](LICENSE.txt) diff --git a/README.md b/README.md new file mode 100644 index 0000000..7aa9ca2 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Talkpal - Frontend + +This is the **frontend** for the **Meeting Room Booking System**, built using **Godot 4.3**. +It provides a UI for managing meetings, rooms, and schedules. diff --git a/Talkpal.apk b/Talkpal.apk new file mode 100644 index 0000000..f6e6995 Binary files /dev/null and b/Talkpal.apk differ diff --git a/Talkpal.apk.idsig b/Talkpal.apk.idsig new file mode 100644 index 0000000..aa41372 Binary files /dev/null and b/Talkpal.apk.idsig differ diff --git a/assets/comfortel_logo.png b/assets/comfortel_logo.png new file mode 100644 index 0000000..3e171ed Binary files /dev/null and b/assets/comfortel_logo.png differ diff --git a/assets/comfortel_logo.png.import b/assets/comfortel_logo.png.import new file mode 100644 index 0000000..01add56 --- /dev/null +++ b/assets/comfortel_logo.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b7jnjarkiduib" +path="res://.godot/imported/comfortel_logo.png-f15e1acabec7ae2a6f363848bac9dc4c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/comfortel_logo.png" +dest_files=["res://.godot/imported/comfortel_logo.png-f15e1acabec7ae2a6f363848bac9dc4c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/textures/time_setting.tres b/assets/textures/time_setting.tres new file mode 100644 index 0000000..6cb837b --- /dev/null +++ b/assets/textures/time_setting.tres @@ -0,0 +1,12 @@ +[gd_resource type="GradientTexture2D" load_steps=2 format=3 uid="uid://d0llucl6yfmwj"] + +[sub_resource type="Gradient" id="Gradient_4ltd2"] +offsets = PackedFloat32Array(0, 0.545455, 0.551948, 1) +colors = PackedColorArray(0.117647, 0.101961, 0.101961, 1, 0.117647, 0.101961, 0.101961, 1, 1, 1, 1, 0, 1, 1, 1, 0) + +[resource] +gradient = SubResource("Gradient_4ltd2") +width = 1024 +height = 1024 +fill = 1 +fill_from = Vector2(0.5, 0.5) diff --git a/assets/themes/big.tres b/assets/themes/big.tres new file mode 100644 index 0000000..5d36172 --- /dev/null +++ b/assets/themes/big.tres @@ -0,0 +1,4 @@ +[gd_resource type="Theme" format=3 uid="uid://cmhwbyqu6nh38"] + +[resource] +default_font_size = 46 diff --git a/assets/themes/medium.tres b/assets/themes/medium.tres new file mode 100644 index 0000000..8866de3 --- /dev/null +++ b/assets/themes/medium.tres @@ -0,0 +1,4 @@ +[gd_resource type="Theme" format=3 uid="uid://7lcget51crj1"] + +[resource] +default_font_size = 42 diff --git a/assets/themes/panel_cyan.tres b/assets/themes/panel_cyan.tres new file mode 100644 index 0000000..8cbb43b --- /dev/null +++ b/assets/themes/panel_cyan.tres @@ -0,0 +1,12 @@ +[gd_resource type="StyleBoxFlat" format=3 uid="uid://crantichmjy77"] + +[resource] +bg_color = Color(0, 0.694118, 0.631373, 0.839216) +border_width_left = 3 +border_width_top = 3 +border_width_bottom = 3 +border_blend = true +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 diff --git a/assets/themes/time_font.tres b/assets/themes/time_font.tres new file mode 100644 index 0000000..38b5aad --- /dev/null +++ b/assets/themes/time_font.tres @@ -0,0 +1,4 @@ +[gd_resource type="Theme" format=3 uid="uid://c5nehi7j4wsjd"] + +[resource] +default_font_size = 145 diff --git a/export_presets.cfg b/export_presets.cfg new file mode 100644 index 0000000..6c55ace --- /dev/null +++ b/export_presets.cfg @@ -0,0 +1,205 @@ +[preset.0] + +name="Android" +platform="Android" +runnable=true +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="./Talkpal.apk" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +gradle_build/use_gradle_build=false +gradle_build/export_format=0 +gradle_build/min_sdk="" +gradle_build/target_sdk="" +architectures/armeabi-v7a=false +architectures/arm64-v8a=true +architectures/x86=false +architectures/x86_64=false +version/code=1 +version/name="" +package/unique_name="com.example.$genname" +package/name="" +package/signed=true +package/app_category=6 +package/retain_data_on_uninstall=false +package/exclude_from_recents=false +package/show_in_android_tv=false +package/show_in_app_library=true +package/show_as_launcher_app=false +launcher_icons/main_192x192="" +launcher_icons/adaptive_foreground_432x432="" +launcher_icons/adaptive_background_432x432="" +graphics/opengl_debug=false +xr_features/xr_mode=0 +screen/immersive_mode=true +screen/support_small=true +screen/support_normal=true +screen/support_large=true +screen/support_xlarge=true +user_data_backup/allow=false +command_line/extra_args="" +apk_expansion/enable=false +apk_expansion/SALT="" +apk_expansion/public_key="" +permissions/custom_permissions=PackedStringArray() +permissions/access_checkin_properties=false +permissions/access_coarse_location=false +permissions/access_fine_location=false +permissions/access_location_extra_commands=false +permissions/access_mock_location=false +permissions/access_network_state=false +permissions/access_surface_flinger=false +permissions/access_wifi_state=false +permissions/account_manager=false +permissions/add_voicemail=false +permissions/authenticate_accounts=false +permissions/battery_stats=false +permissions/bind_accessibility_service=false +permissions/bind_appwidget=false +permissions/bind_device_admin=false +permissions/bind_input_method=false +permissions/bind_nfc_service=false +permissions/bind_notification_listener_service=false +permissions/bind_print_service=false +permissions/bind_remoteviews=false +permissions/bind_text_service=false +permissions/bind_vpn_service=false +permissions/bind_wallpaper=false +permissions/bluetooth=false +permissions/bluetooth_admin=false +permissions/bluetooth_privileged=false +permissions/brick=false +permissions/broadcast_package_removed=false +permissions/broadcast_sms=false +permissions/broadcast_sticky=false +permissions/broadcast_wap_push=false +permissions/call_phone=false +permissions/call_privileged=false +permissions/camera=false +permissions/capture_audio_output=false +permissions/capture_secure_video_output=false +permissions/capture_video_output=false +permissions/change_component_enabled_state=false +permissions/change_configuration=false +permissions/change_network_state=false +permissions/change_wifi_multicast_state=false +permissions/change_wifi_state=false +permissions/clear_app_cache=false +permissions/clear_app_user_data=false +permissions/control_location_updates=false +permissions/delete_cache_files=false +permissions/delete_packages=false +permissions/device_power=false +permissions/diagnostic=false +permissions/disable_keyguard=false +permissions/dump=false +permissions/expand_status_bar=false +permissions/factory_test=false +permissions/flashlight=false +permissions/force_back=false +permissions/get_accounts=false +permissions/get_package_size=false +permissions/get_tasks=false +permissions/get_top_activity_info=false +permissions/global_search=false +permissions/hardware_test=false +permissions/inject_events=false +permissions/install_location_provider=false +permissions/install_packages=false +permissions/install_shortcut=false +permissions/internal_system_window=false +permissions/internet=false +permissions/kill_background_processes=false +permissions/location_hardware=false +permissions/manage_accounts=false +permissions/manage_app_tokens=false +permissions/manage_documents=false +permissions/manage_external_storage=false +permissions/master_clear=false +permissions/media_content_control=false +permissions/modify_audio_settings=false +permissions/modify_phone_state=false +permissions/mount_format_filesystems=false +permissions/mount_unmount_filesystems=false +permissions/nfc=false +permissions/persistent_activity=false +permissions/post_notifications=false +permissions/process_outgoing_calls=false +permissions/read_calendar=false +permissions/read_call_log=false +permissions/read_contacts=false +permissions/read_external_storage=false +permissions/read_frame_buffer=false +permissions/read_history_bookmarks=false +permissions/read_input_state=false +permissions/read_logs=false +permissions/read_phone_state=false +permissions/read_profile=false +permissions/read_sms=false +permissions/read_social_stream=false +permissions/read_sync_settings=false +permissions/read_sync_stats=false +permissions/read_user_dictionary=false +permissions/reboot=false +permissions/receive_boot_completed=false +permissions/receive_mms=false +permissions/receive_sms=false +permissions/receive_wap_push=false +permissions/record_audio=false +permissions/reorder_tasks=false +permissions/restart_packages=false +permissions/send_respond_via_message=false +permissions/send_sms=false +permissions/set_activity_watcher=false +permissions/set_alarm=false +permissions/set_always_finish=false +permissions/set_animation_scale=false +permissions/set_debug_app=false +permissions/set_orientation=false +permissions/set_pointer_speed=false +permissions/set_preferred_applications=false +permissions/set_process_limit=false +permissions/set_time=false +permissions/set_time_zone=false +permissions/set_wallpaper=false +permissions/set_wallpaper_hints=false +permissions/signal_persistent_processes=false +permissions/status_bar=false +permissions/subscribed_feeds_read=false +permissions/subscribed_feeds_write=false +permissions/system_alert_window=false +permissions/transmit_ir=false +permissions/uninstall_shortcut=false +permissions/update_device_stats=false +permissions/use_credentials=false +permissions/use_sip=false +permissions/vibrate=false +permissions/wake_lock=false +permissions/write_apn_settings=false +permissions/write_calendar=false +permissions/write_call_log=false +permissions/write_contacts=false +permissions/write_external_storage=false +permissions/write_gservices=false +permissions/write_history_bookmarks=false +permissions/write_profile=false +permissions/write_secure_settings=false +permissions/write_settings=false +permissions/write_sms=false +permissions/write_social_stream=false +permissions/write_sync_settings=false +permissions/write_user_dictionary=false +dotnet/include_scripts_content=false +dotnet/include_debug_symbols=false +dotnet/embed_build_outputs=false diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..3fe4f4a --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..7e0ee75 --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d4gjit28wdndu" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/override.cfg b/override.cfg new file mode 100644 index 0000000..d2cce21 --- /dev/null +++ b/override.cfg @@ -0,0 +1,36 @@ +; Project settings override file. +; Adds gamepad inputs to built-in actions. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + + +[input] + +ui_accept={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194309,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194310,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":32,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null) +] +} +ui_cancel={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194305,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":6,"pressure":0.0,"pressed":true,"script":null) +] +} +ui_page_up={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194323,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":true,"script":null) +] +} +ui_page_down={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194324,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":true,"script":null) +] +} diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..ce28135 --- /dev/null +++ b/project.godot @@ -0,0 +1,56 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Talkpal" +run/main_scene="res://scenes/main/main_mobile.tscn" +config/features=PackedStringArray("4.2", "GL Compatibility") +boot_splash/bg_color=Color(0.800491, 0.800491, 0.800491, 1) +boot_splash/image="res://assets/comfortel_logo.png" +config/icon="res://assets/comfortel_logo.png" + +[autoload] + +AppConfig="*res://addons/maaacks_menus_template/base/scenes/autoloads/app_config.tscn" +SceneLoader="*res://addons/maaacks_menus_template/base/scenes/autoloads/scene_loader.tscn" +ProjectMusicController="*res://addons/maaacks_menus_template/base/scenes/autoloads/project_music_controller.tscn" +ProjectUISoundController="*res://addons/maaacks_menus_template/base/scenes/autoloads/project_ui_sound_controller.tscn" +uuid="*res://addons/uuid/uuid.gd" + +[display] + +window/size/viewport_width=1080 +window/size/viewport_height=2340 +window/stretch/aspect="keep_width" +window/handheld/orientation=1 + +[dotnet] + +project/assembly_name="Talkpal Frontend" + +[editor_plugins] + +enabled=PackedStringArray("res://addons/maaacks_menus_template/plugin.cfg", "res://addons/uuid/plugin.cfg") + +[internationalization] + +locale/translations=PackedStringArray("res://addons/maaacks_menus_template/base/translations/menus_translations.en.translation", "res://addons/maaacks_menus_template/base/translations/menus_translations.fr.translation") + +[maaacks_menus_template] + +disable_plugin_dialogues=true +copy_path="res://" + +[rendering] + +renderer/rendering_method="gl_compatibility" +renderer/rendering_method.mobile="gl_compatibility" +textures/vram_compression/import_etc2_astc=true diff --git a/scenes/board/board.gd b/scenes/board/board.gd new file mode 100644 index 0000000..4b1d81d --- /dev/null +++ b/scenes/board/board.gd @@ -0,0 +1,121 @@ +extends VBoxContainer + +const TimeSlot = preload("res://scenes/board/time_slot.tscn") +const ReservationScene = preload("res://scenes/board/reservation.tscn") +const ReservationIndent = preload("res://scenes/board/reservation_indent.tscn") + +const WorkingDayStart = 8 +const WorkingDayEnd = 21 + +const MinimalMinutesToShowTitle = 30 + +const MockedSchedule = [ + { + "title": "Психолог", + "start_time": 120, + "end_time": 180, + "color": 1 + }, + { + "title": "Дипал", + "start_time": 180, + "end_time": 210, + "color": 2 + }, + { + "title": "Маркетинг", + "start_time": 280, + "end_time": 325, + "color": 3 + } +] + +@onready var _main: Main = get_tree().get_current_scene() +@onready var _timeline = $Panel/Timeline +@onready var _reservations = $Panel/Reservations + +func _ready(): + _remove_time_slots() + _remove_reservations() + + _fill_with_slots() + _update_schedule() + +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 _update_schedule(): + if not _main.is_node_ready(): + await _main.ready + + var repo = _main.get_reservation_repo() + var previous_finish_time = 0 + + for reservation in repo.list_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_indent(start_time - previous_finish_time) + _compose_reservation(reservation_time, reservation.title, reservation.color) + + previous_finish_time = finish_time + +func _compose_indent(minutes): + var indent = ReservationIndent.instantiate() + _reservations.add_child(indent) + indent.set_minutes(minutes) + +func _compose_reservation(minutes, title, color): + if minutes <= MinimalMinutesToShowTitle: + title = "" + + var reservation = ReservationScene.instantiate() + _reservations.add_child(reservation) + reservation.set_minutes(minutes) + reservation.set_title(title) + reservation.set_color(color) + +func _input(event): + 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 _main.get_current_page() == Main.Pages.Board: + _main.load_page(Main.Pages.ReservationCreation) + +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 _on_room_button_pressed(): + print("emit change room signal") + +func _on_date_button_pressed(): + print("emit change date signal") + +func update(): + _ready() diff --git a/scenes/board/board.tscn b/scenes/board/board.tscn new file mode 100644 index 0000000..0840540 --- /dev/null +++ b/scenes/board/board.tscn @@ -0,0 +1,57 @@ +[gd_scene load_steps=6 format=3 uid="uid://c431r28ef5edp"] + +[ext_resource type="Script" path="res://scenes/board/board.gd" id="1_2wgc4"] +[ext_resource type="Theme" uid="uid://cmhwbyqu6nh38" path="res://assets/themes/big.tres" id="1_na0ey"] +[ext_resource type="PackedScene" uid="uid://cnr23ry08ntv4" path="res://scenes/board/time_slot.tscn" id="2_kklmx"] +[ext_resource type="PackedScene" uid="uid://blv30rxduydmw" path="res://scenes/board/reservation_indent.tscn" id="3_mltgm"] +[ext_resource type="PackedScene" uid="uid://dpi5ft4r8sfwb" path="res://scenes/board/reservation.tscn" id="4_o5rhy"] + +[node name="Board" type="VBoxContainer"] +anchors_preset = 10 +anchor_right = 1.0 +offset_bottom = 75.0 +grow_horizontal = 2 +theme_override_constants/separation = 50 +script = ExtResource("1_2wgc4") + +[node name="TopBar" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="RoomButton" type="Button" parent="TopBar"] +layout_mode = 2 +theme = ExtResource("1_na0ey") +text = "Переговорка 1" + +[node name="DateButton" type="Button" parent="TopBar"] +layout_mode = 2 +size_flags_horizontal = 10 +theme = ExtResource("1_na0ey") +text = "Вт, 14 июн. 2022" + +[node name="Panel" type="Control" parent="."] +layout_mode = 2 + +[node name="Timeline" type="VBoxContainer" parent="Panel"] +layout_mode = 2 +offset_top = 50.0 +offset_right = 1036.0 +offset_bottom = 354.0 + +[node name="TimeSlot" parent="Panel/Timeline" instance=ExtResource("2_kklmx")] +layout_mode = 2 + +[node name="TimeSlot2" parent="Panel/Timeline" instance=ExtResource("2_kklmx")] +layout_mode = 2 + +[node name="Reservations" type="VBoxContainer" parent="Panel"] +layout_mode = 2 +offset_top = 50.0 +offset_right = 1036.0 +offset_bottom = 117.0 +grow_horizontal = 2 + +[node name="Indent" parent="Panel/Reservations" instance=ExtResource("3_mltgm")] +layout_mode = 2 + +[node name="Reservation" parent="Panel/Reservations" instance=ExtResource("4_o5rhy")] +layout_mode = 2 diff --git a/scenes/board/reservation.gd b/scenes/board/reservation.gd new file mode 100644 index 0000000..4c6a4ed --- /dev/null +++ b/scenes/board/reservation.gd @@ -0,0 +1,36 @@ +extends HBoxContainer +class_name Reservation + +const HourSize = 150 + +const Colors = { + 1: Color("00b1a1d6"), + 2: Color("f431e0d6"), + 3: Color("eb7130d6") +} + +@onready var _main: Main = get_tree().get_current_scene() +@onready var _title = $Section/SectionLabel +@onready var _panel = $Section/SectionPanel + +func _ready(): + initialize_signals() + +func initialize_signals(): + _panel.gui_input.connect(_on_section_panel_gui_input) + +func set_title(title): + _title.text = title + +func set_minutes(minutes): + _panel.size.y = minutes * HourSize / 60 + custom_minimum_size.y = _panel.size.y + +func set_color(color): + var new_style_box: StyleBoxFlat = _panel.get("theme_override_styles/panel").duplicate() + new_style_box.bg_color = Colors[color] + _panel.set("theme_override_styles/panel", new_style_box) + +func _on_section_panel_gui_input(event): + if event is InputEventScreenTouch or (event is InputEventMouseButton and event.pressed): + print("emit open reservation info signal") diff --git a/scenes/board/reservation.tscn b/scenes/board/reservation.tscn new file mode 100644 index 0000000..ef9a646 --- /dev/null +++ b/scenes/board/reservation.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=4 format=3 uid="uid://dpi5ft4r8sfwb"] + +[ext_resource type="Script" path="res://scenes/board/reservation.gd" id="1_drhpx"] +[ext_resource type="Theme" uid="uid://cmhwbyqu6nh38" path="res://assets/themes/big.tres" id="2_vfg04"] +[ext_resource type="StyleBox" uid="uid://crantichmjy77" path="res://assets/themes/panel_cyan.tres" id="3_xwx35"] + +[node name="Reservation" type="HBoxContainer"] +custom_minimum_size = Vector2(0, 200) +offset_right = 157.0 +offset_bottom = 200.0 +script = ExtResource("1_drhpx") + +[node name="Indent" type="Label" parent="."] +layout_mode = 2 +theme = ExtResource("2_vfg04") +theme_override_colors/font_color = Color(0, 0, 0, 0) +text = "11:00 " + +[node name="Section" type="Control" parent="."] +layout_mode = 2 + +[node name="SectionPanel" type="Panel" parent="Section"] +layout_mode = 1 +offset_right = 883.0 +offset_bottom = 200.0 +size_flags_horizontal = 3 +theme_override_styles/panel = ExtResource("3_xwx35") + +[node name="SectionLabel" type="Label" parent="Section"] +layout_mode = 1 +anchors_preset = 4 +anchor_top = 0.5 +anchor_bottom = 0.5 +offset_left = 50.0 +offset_top = -33.5 +offset_right = 396.0 +offset_bottom = 33.5 +grow_vertical = 2 +theme = ExtResource("2_vfg04") +text = "Интервью C++" diff --git a/scenes/board/reservation_indent.gd b/scenes/board/reservation_indent.gd new file mode 100644 index 0000000..37b3c95 --- /dev/null +++ b/scenes/board/reservation_indent.gd @@ -0,0 +1,6 @@ +extends Control + +const HourSize = 150 + +func set_minutes(minutes): + custom_minimum_size.y = minutes * HourSize / 60 diff --git a/scenes/board/reservation_indent.tscn b/scenes/board/reservation_indent.tscn new file mode 100644 index 0000000..4318857 --- /dev/null +++ b/scenes/board/reservation_indent.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://blv30rxduydmw"] + +[ext_resource type="Script" path="res://scenes/board/reservation_indent.gd" id="1_pq834"] + +[node name="Indent" type="Control"] +custom_minimum_size = Vector2(0, 50) +layout_mode = 3 +anchors_preset = 0 +script = ExtResource("1_pq834") diff --git a/scenes/board/time_slot.gd b/scenes/board/time_slot.gd new file mode 100644 index 0000000..3d6c09a --- /dev/null +++ b/scenes/board/time_slot.gd @@ -0,0 +1,6 @@ +extends HBoxContainer + +@onready var _time_label = $TimeLabelControl/TimeLabel + +func set_time(hour): + _time_label.text = str(hour) + ":00" diff --git a/scenes/board/time_slot.tscn b/scenes/board/time_slot.tscn new file mode 100644 index 0000000..018acd0 --- /dev/null +++ b/scenes/board/time_slot.tscn @@ -0,0 +1,62 @@ +[gd_scene load_steps=4 format=3 uid="uid://cnr23ry08ntv4"] + +[ext_resource type="Script" path="res://scenes/board/time_slot.gd" id="1_hwvwy"] +[ext_resource type="Theme" uid="uid://cmhwbyqu6nh38" path="res://assets/themes/big.tres" id="2_ty4oc"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_pfkqv"] +bg_color = Color(0.6, 0.6, 0.6, 0) +border_width_left = 3 +border_width_top = 3 +border_width_bottom = 3 +border_blend = true +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[node name="TimeSlot" type="HBoxContainer"] +custom_minimum_size = Vector2(0, 150) +theme_override_constants/separation = 25 +script = ExtResource("1_hwvwy") + +[node name="Indent" type="Label" parent="."] +layout_mode = 2 +theme = ExtResource("2_ty4oc") +text = " " + +[node name="TimeLabelControl" type="Control" parent="."] +layout_mode = 2 + +[node name="TimeLabel" type="Label" parent="TimeLabelControl"] +layout_mode = 1 +anchors_preset = 6 +anchor_left = 1.0 +anchor_top = 0.5 +anchor_right = 1.0 +anchor_bottom = 0.5 +offset_left = -121.0 +offset_top = -33.5 +offset_bottom = 33.5 +grow_horizontal = 0 +grow_vertical = 2 +theme = ExtResource("2_ty4oc") +text = "11:00" + +[node name="Section" type="Panel" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_styles/panel = SubResource("StyleBoxFlat_pfkqv") + +[node name="EventsContainer" type="GridContainer" parent="."] +visible = false +layout_mode = 2 + +[node name="Event" type="Button" parent="EventsContainer"] +layout_mode = 2 +theme = ExtResource("2_ty4oc") +text = "Переговоры с Клиентами" + +[node name="Event2" type="Button" parent="EventsContainer"] +layout_mode = 2 +theme = ExtResource("2_ty4oc") +text = "Интервью C#" diff --git a/scenes/common/calendar/calendar_edit.gd b/scenes/common/calendar/calendar_edit.gd new file mode 100644 index 0000000..e07a0bf --- /dev/null +++ b/scenes/common/calendar/calendar_edit.gd @@ -0,0 +1 @@ +extends Control diff --git a/scenes/common/calendar/calendar_edit.tscn b/scenes/common/calendar/calendar_edit.tscn new file mode 100644 index 0000000..205072f --- /dev/null +++ b/scenes/common/calendar/calendar_edit.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=3 format=3 uid="uid://drdv8adk1wi8f"] + +[ext_resource type="Script" path="res://scenes/common/calendar/calendar_edit.gd" id="1_jxhnl"] +[ext_resource type="Theme" uid="uid://cmhwbyqu6nh38" path="res://assets/themes/big.tres" id="2_e6eik"] + +[node name="Calendar" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_jxhnl") + +[node name="Button" type="Button" parent="."] +layout_mode = 0 +offset_right = 24.0 +offset_bottom = 31.0 +theme = ExtResource("2_e6eik") +text = "Открыть календарь" diff --git a/scenes/common/edit_field.gd b/scenes/common/edit_field.gd new file mode 100644 index 0000000..5aee32e --- /dev/null +++ b/scenes/common/edit_field.gd @@ -0,0 +1,86 @@ +@tool +extends HBoxContainer + +enum Type { + Line, + Text, + Calendar, + Time +} + +@export var title : String: + set(value): + title = value + set_title(title) + +@export var type := Type.Line: + set(value): + type = value + set_type(type) + +@onready var _label = $FieldLabelControl/FieldLabel +@onready var _line = $Line +@onready var _calendar = $Calendar +@onready var _time = $Time +@onready var _text = $Text + +var _type + +func _ready(): + set_title(title) + set_type(type) + +func set_title(new_title): + if _label == null: + await ready + + _label.text = new_title + +func get_value(): + match _type: + Type.Line: + return _line.text + Type.Text: + return _text.text + Type.Calendar: + return "" + Type.Time: + return { + "hours": _time.get_hours(), + "minutes": _time.get_minutes() + } + +func set_value(value): + _line.text = value + +func set_type(type): + if _line == null: + await ready + + _line.visible = false + _text.visible = false + _calendar.visible = false + _time.visible = false + + _type = type + + match type: + Type.Line: + _line.visible = true + Type.Text: + _text.visible = true + Type.Calendar: + _calendar.visible = true + Type.Time: + _time.visible = true + +func clean(): + match _type: + Type.Line: + _line.text = "" + Type.Text: + _text.text = "" + Type.Calendar: + pass + Type.Time: + _time.clean() diff --git a/scenes/common/edit_field.tscn b/scenes/common/edit_field.tscn new file mode 100644 index 0000000..b2bdf3d --- /dev/null +++ b/scenes/common/edit_field.tscn @@ -0,0 +1,53 @@ +[gd_scene load_steps=6 format=3 uid="uid://d0fdiesiaajlq"] + +[ext_resource type="Script" path="res://scenes/common/edit_field.gd" id="1_sdy7t"] +[ext_resource type="Theme" uid="uid://7lcget51crj1" path="res://assets/themes/medium.tres" id="1_v1b42"] +[ext_resource type="Theme" uid="uid://cmhwbyqu6nh38" path="res://assets/themes/big.tres" id="2_iq8f3"] +[ext_resource type="PackedScene" uid="uid://drdv8adk1wi8f" path="res://scenes/common/calendar/calendar_edit.tscn" id="4_hlx5p"] +[ext_resource type="PackedScene" uid="uid://bhd0xvnvoqslr" path="res://scenes/common/time/time_edit.tscn" id="5_d0drs"] + +[node name="EditField" type="HBoxContainer"] +anchors_preset = 10 +anchor_right = 1.0 +offset_bottom = 67.0 +grow_horizontal = 2 +theme_override_constants/separation = 25 +script = ExtResource("1_sdy7t") + +[node name="FieldLabelControl" type="Control" parent="."] +layout_mode = 2 + +[node name="FieldLabel" type="Label" parent="FieldLabelControl"] +layout_mode = 2 +offset_left = 25.0 +offset_top = 4.0 +offset_right = 231.0 +offset_bottom = 62.0 +theme = ExtResource("1_v1b42") + +[node name="Indent" type="Label" parent="."] +layout_mode = 2 +theme = ExtResource("2_iq8f3") +text = " " + +[node name="Line" type="LineEdit" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +theme = ExtResource("2_iq8f3") + +[node name="Text" type="TextEdit" parent="."] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +theme = ExtResource("2_iq8f3") +wrap_mode = 1 +scroll_fit_content_height = true + +[node name="Calendar" parent="." instance=ExtResource("4_hlx5p")] +visible = false +layout_mode = 2 + +[node name="Time" parent="." instance=ExtResource("5_d0drs")] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 diff --git a/scenes/common/time/time_edit.gd b/scenes/common/time/time_edit.gd new file mode 100644 index 0000000..36f0c47 --- /dev/null +++ b/scenes/common/time/time_edit.gd @@ -0,0 +1,41 @@ +extends Control + +@onready var _main: Main = get_tree().get_current_scene() +@onready var _edit := $Edit + +var _hours := 0 +var _minutes := 0 +var _time_setting_page + +func _ready(): + initialize_signals() + +func initialize_signals(): + _edit.focus_entered.connect(_on_click) + +func _on_click(): + if _main.get_current_page() == Main.Pages.TimeSetting: + return + + _time_setting_page = _main.load_page(Main.Pages.TimeSetting) + _time_setting_page.time_is_set.connect(self._on_time_is_set) + +func _on_time_is_set(hours: int, minutes: int): + _time_setting_page.time_is_set.disconnect(_on_time_is_set) + _edit.text = str(hours) + ":" + _correct_minutes(str(minutes)) + _hours = hours + _minutes = minutes + +func _correct_minutes(value): + return "0" + value if len(value) == 1 else value + +func get_hours(): + return _hours + +func get_minutes(): + return _minutes + +func clean(): + _hours = 0 + _minutes = 0 + _edit.text = "" diff --git a/scenes/common/time/time_edit.tscn b/scenes/common/time/time_edit.tscn new file mode 100644 index 0000000..e9e55e3 --- /dev/null +++ b/scenes/common/time/time_edit.tscn @@ -0,0 +1,31 @@ +[gd_scene load_steps=4 format=3 uid="uid://bhd0xvnvoqslr"] + +[ext_resource type="Script" path="res://scenes/common/time/time_edit.gd" id="1_2wxyg"] +[ext_resource type="Script" path="res://addons/date-time-elements/scripts/time-input.gd" id="2_7d4ae"] +[ext_resource type="Theme" uid="uid://cmhwbyqu6nh38" path="res://assets/themes/big.tres" id="3_bpvuo"] + +[node name="Time" type="BoxContainer"] +anchors_preset = 10 +anchor_right = 1.0 +offset_bottom = 75.0 +grow_horizontal = 2 +script = ExtResource("1_2wxyg") + +[node name="TimeEdit" type="LineEdit" parent="."] +visible = false +layout_mode = 2 +text = "21:15 " +placeholder_text = "hh:mm (a/p)m" +script = ExtResource("2_7d4ae") +current_time = true + +[node name="Edit" type="LineEdit" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +theme = ExtResource("3_bpvuo") +virtual_keyboard_enabled = false + +[connection signal="mouse_entered" from="TimeEdit/Clock" to="TimeEdit/Clock" method="_on_mouse_entered"] +[connection signal="mouse_exited" from="TimeEdit/Clock" to="TimeEdit/Clock" method="_on_mouse_exited"] +[connection signal="visibility_changed" from="TimeEdit/Clock" to="TimeEdit/Clock" method="_on_visibility_changed"] +[connection signal="draw" from="TimeEdit/ManualClock" to="TimeEdit/ManualClock" method="_on_draw"] diff --git a/scenes/common/time/time_hand.gd b/scenes/common/time/time_hand.gd new file mode 100644 index 0000000..859f5a4 --- /dev/null +++ b/scenes/common/time/time_hand.gd @@ -0,0 +1,40 @@ +@tool +extends Marker2D + +@onready var number = $Number +@onready var number_label = $Number/Label + +@export_range(0, 12, 1, "o'clock") var part : float: + set(value): + part = value + set_part(part) + +@export var value : int: + set(new_value): + value = new_value + await ready + set_value(value) + +var _part: float +var _value: int + +func _process(delta): + number.rotation = -rotation + +func set_part(value): + _part = value + var new_rotation = 2*PI * value / 12 + rotation = new_rotation + +func get_part(): + return _part + +func set_value(new_value): + _value = new_value + number_label.text = str(new_value) + +func get_value(): + return _value + +func get_number_position(): + return number.global_position diff --git a/scenes/common/time/time_hand.tscn b/scenes/common/time/time_hand.tscn new file mode 100644 index 0000000..f80edf6 --- /dev/null +++ b/scenes/common/time/time_hand.tscn @@ -0,0 +1,54 @@ +[gd_scene load_steps=4 format=3 uid="uid://3omkos3a4po7"] + +[ext_resource type="Theme" uid="uid://cmhwbyqu6nh38" path="res://assets/themes/big.tres" id="1_ne7tv"] +[ext_resource type="Script" path="res://scenes/common/time/time_hand.gd" id="1_tiohc"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5bs5k"] +bg_color = Color(1, 1, 1, 0) +corner_radius_top_left = 250 +corner_radius_top_right = 250 +corner_radius_bottom_right = 250 +corner_radius_bottom_left = 250 +anti_aliasing_size = 0.01 + +[node name="Hand" type="Marker2D"] +script = ExtResource("1_tiohc") + +[node name="TapArea" type="Panel" parent="."] +modulate = Color(0.282353, 0.580392, 0.235294, 1) +offset_left = -44.0 +offset_top = -345.0 +offset_right = 45.0 +offset_bottom = -256.0 +theme_override_styles/panel = SubResource("StyleBoxFlat_5bs5k") + +[node name="Number" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_top = -301.0 +offset_right = 1.0 +offset_bottom = -301.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Label" type="Label" parent="Number"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -27.0 +offset_top = -34.0 +offset_right = 27.0 +offset_bottom = 33.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("1_ne7tv") +text = "20" +horizontal_alignment = 1 +vertical_alignment = 1 diff --git a/scenes/common/time/time_setting.gd b/scenes/common/time/time_setting.gd new file mode 100644 index 0000000..024f1dd --- /dev/null +++ b/scenes/common/time/time_setting.gd @@ -0,0 +1,175 @@ +extends Control + +const TimeHand = preload("res://scenes/common/time/time_hand.tscn") + +const WorkingDayStart = 8 +const WorkingDayEnd = 21 + +const DigitsNumber = 12 + +enum State { + SettingHours, + SettingMinutes +} + +@export var number_flash_time := 0.5 + +@onready var _main: Main = get_tree().get_current_scene() +@onready var _hours_label = $VerticalBar/Time/Hours +@onready var _minutes_label = $VerticalBar/Time/Minutes +@onready var _time = $VerticalBar/Time +@onready var _face = $VerticalBar/Circle/Face +@onready var _arrow = $VerticalBar/Circle/Clock/Arrow +@onready var _numbers = $VerticalBar/Circle/Clock/Numbers + +var _hours : int +var _minutes : int + +var _state := State.SettingHours +var _time_after_last_flash := 0.0 + +signal time_is_set(hours: int, minutes: int) + +func _ready(): + _set_initial_values() + _start_hours_setting() + +func _set_initial_values(): + _hours = WorkingDayStart + _minutes = 0 + +func _process(delta): + if _time_after_last_flash >= number_flash_time: + _flash_number() + _time_after_last_flash = 0.0 + + _time_after_last_flash += delta + +func _flash_number(): + match _state: + State.SettingHours: + _hours_label.text = str(_hours) \ + if _hours_label.text == '_' else '_' + State.SettingMinutes: + _minutes_label.text = _correct_minutes(str(_minutes)) \ + if _minutes_label.text == '_' else '_' + +func _fill_with_hours(): + _remove_numbers() + for part in range(0, DigitsNumber): + var number = TimeHand.instantiate() + _numbers.add_child(number) + number.set_part(part) + number.set_value(WorkingDayStart + part) + +func _fill_with_minutes(): + _remove_numbers() + for part in range(0, DigitsNumber): + var number = TimeHand.instantiate() + _numbers.add_child(number) + number.set_part(part) + number.set_value(5*part) + +func _remove_numbers(): + for number in _numbers.get_children(): + number.queue_free() + +func _clicked_on_face(pos: Vector2): + var face_position = _face.global_position + return (pos.x > face_position.x and pos.x < _face.size.x + face_position.x) and \ + (pos.y > face_position.y and pos.y < _face.size.y + face_position.y) + +func _clicked_on_time(pos: Vector2): + var time_position = _time.global_position + return (pos.x > time_position.x and pos.x < _time.size.x + time_position.x) and \ + (pos.y > time_position.y and pos.y < _time.size.y + time_position.y) + +func _input(event): + if not _main.get_current_page() == Main.Pages.TimeSetting: + return + + if (event is InputEventScreenTouch and event.pressed) or \ + (event is InputEventMouseButton and event.pressed): # TODO: call on click or release, do not do anything if it was clicked + if _clicked_on_face(event.position): + var number = _get_closest_number(event.position) + _arrow.rotation = number.rotation + + match _state: + State.SettingHours: + set_hours(number.get_value()) + await get_tree().create_timer(0.01, false).timeout + _start_minutes_setting() + State.SettingMinutes: + set_minutes(number.get_value()) + time_is_set.emit(_hours, _minutes) + await get_tree().create_timer(0.01, false).timeout + _main.go_to_previous_page() + _ready() + + elif _clicked_on_time(event.position): + match _get_closest_unit(event.position): + _hours_label: + _start_hours_setting() + _minutes_label: + _start_minutes_setting() + + await event.is_released() == true + +func _get_closest_number(pos: Vector2): + var min_distance = INF + var sought = null + + for number in _numbers.get_children(): + var distance = number.get_number_position().distance_to(pos) + if (distance < min_distance): + min_distance = distance + sought = number + + return sought + +func _get_closest_unit(pos: Vector2): + var min_distance = INF + var sought = null + + for unit in _time.get_children(): + var distance = unit.global_position.distance_to(pos) + if (distance < min_distance): + min_distance = distance + sought = unit + + return sought + +func set_hours(value): + _hours = value + _update_time() + +func get_hours(): + return _hours + +func set_minutes(value): + _minutes = value + _update_time() + +func get_minutes(): + return _minutes + +func _update_time(): + _arrow.rotation = 0.0 + _hours_label.text = str(_hours) + _minutes_label.text = _correct_minutes(str(_minutes)) + +func _correct_minutes(value): + return "0" + value if len(value) == 1 else value + +func _start_hours_setting(): + _state = State.SettingHours + _fill_with_hours() + _update_time() + +func _start_minutes_setting(): + _state = State.SettingMinutes + _fill_with_minutes() + _update_time() + +func update(): + _ready() diff --git a/scenes/common/time/time_setting.tscn b/scenes/common/time/time_setting.tscn new file mode 100644 index 0000000..534b805 --- /dev/null +++ b/scenes/common/time/time_setting.tscn @@ -0,0 +1,131 @@ +[gd_scene load_steps=7 format=3 uid="uid://cxs8xe5w32jo4"] + +[ext_resource type="Script" path="res://scenes/common/time/time_setting.gd" id="1_2uqfu"] +[ext_resource type="Texture2D" uid="uid://d0llucl6yfmwj" path="res://assets/textures/time_setting.tres" id="2_6xoc0"] +[ext_resource type="Theme" uid="uid://c5nehi7j4wsjd" path="res://assets/themes/time_font.tres" id="3_gngar"] +[ext_resource type="PackedScene" uid="uid://3omkos3a4po7" path="res://scenes/common/time/time_hand.tscn" id="4_g84y5"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_23ktd"] +bg_color = Color(1, 1, 1, 1) +corner_radius_top_left = 250 +corner_radius_top_right = 250 +corner_radius_bottom_right = 250 +corner_radius_bottom_left = 250 +anti_aliasing_size = 0.01 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5mbj6"] +bg_color = Color(1, 1, 1, 1) + +[node name="TimeSetting" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_2uqfu") + +[node name="VerticalBar" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -20.0 +offset_top = -20.0 +offset_right = 20.0 +offset_bottom = 20.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Time" type="HBoxContainer" parent="VerticalBar"] +layout_mode = 2 +theme = ExtResource("3_gngar") +alignment = 1 + +[node name="Hours" type="Label" parent="VerticalBar/Time"] +layout_mode = 2 +text = "_" + +[node name="_" type="Label" parent="VerticalBar/Time"] +layout_mode = 2 +text = ":" + +[node name="Minutes" type="Label" parent="VerticalBar/Time"] +layout_mode = 2 +text = "00" + +[node name="Circle" type="TextureRect" parent="VerticalBar"] +layout_mode = 2 +texture = ExtResource("2_6xoc0") + +[node name="Face" type="Control" parent="VerticalBar/Circle"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -350.0 +offset_top = -350.0 +offset_right = 350.0 +offset_bottom = 350.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Clock" type="Control" parent="VerticalBar/Circle"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Arrow" type="Marker2D" parent="VerticalBar/Circle/Clock"] + +[node name="Center" type="Panel" parent="VerticalBar/Circle/Clock/Arrow"] +modulate = Color(0.282353, 0.580392, 0.235294, 1) +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -7.5 +offset_top = -7.5 +offset_right = 7.5 +offset_bottom = 7.5 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_23ktd") +metadata/_edit_use_anchors_ = true + +[node name="Circle" type="Panel" parent="VerticalBar/Circle/Clock/Arrow"] +modulate = Color(0.282353, 0.580392, 0.235294, 1) +offset_left = -44.0 +offset_top = -345.0 +offset_right = 45.0 +offset_bottom = -256.0 +theme_override_styles/panel = SubResource("StyleBoxFlat_23ktd") + +[node name="Panel" type="Panel" parent="VerticalBar/Circle/Clock/Arrow"] +modulate = Color(0.282353, 0.580392, 0.235294, 1) +offset_left = 2.0 +offset_top = 2.0 +offset_right = 6.0 +offset_bottom = 274.0 +rotation = 3.14159 +theme_override_styles/panel = SubResource("StyleBoxFlat_5mbj6") + +[node name="Numbers" type="Control" parent="VerticalBar/Circle/Clock"] +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="Hand" parent="VerticalBar/Circle/Clock/Numbers" instance=ExtResource("4_g84y5")] + +[node name="Hand2" parent="VerticalBar/Circle/Clock/Numbers" instance=ExtResource("4_g84y5")] + +[node name="Hand3" parent="VerticalBar/Circle/Clock/Numbers" instance=ExtResource("4_g84y5")] diff --git a/scenes/main/main_mobile.gd b/scenes/main/main_mobile.gd new file mode 100644 index 0000000..7bf0fbe --- /dev/null +++ b/scenes/main/main_mobile.gd @@ -0,0 +1,48 @@ +@tool +extends Control +class_name Main + +enum Pages { + Board, + ReservationCreation, + TimeSetting +} + +@onready var _reservation_repo : AbstractReservationRepo = $Repos/Reservation + +@export var current_page : Pages: + set(value): + current_page = value + load_page(value, false) + +@onready var _pages := { + Pages.Board: $Pages/Board, + Pages.ReservationCreation: $Pages/ReservationCreation, + Pages.TimeSetting: $Pages/TimeSetting +} + +var _current_page := Pages.Board +var _previous_page : Pages + +func get_current_page(): + return _current_page + +func load_page(value, with_update=true): + _pages[_current_page].visible = false + + if _previous_page != _current_page: + _previous_page = _current_page + + _current_page = value + if with_update: + _pages[_current_page].update() + _pages[_current_page].visible = true + + return _pages[_current_page] + +func go_to_previous_page(): + if _previous_page != null: + load_page(_previous_page) + +func get_reservation_repo() -> AbstractReservationRepo: + return _reservation_repo diff --git a/scenes/main/main_mobile.tscn b/scenes/main/main_mobile.tscn new file mode 100644 index 0000000..92d1c0c --- /dev/null +++ b/scenes/main/main_mobile.tscn @@ -0,0 +1,58 @@ +[gd_scene load_steps=6 format=3 uid="uid://drqy50fps66oy"] + +[ext_resource type="Script" path="res://scenes/main/main_mobile.gd" id="1_vo4ao"] +[ext_resource type="PackedScene" uid="uid://c431r28ef5edp" path="res://scenes/board/board.tscn" id="2_brvql"] +[ext_resource type="PackedScene" uid="uid://csfn8q6b5hj4y" path="res://scenes/reservation/reservation_creation.tscn" id="3_qr4p2"] +[ext_resource type="PackedScene" uid="uid://cxs8xe5w32jo4" path="res://scenes/common/time/time_setting.tscn" id="4_popa2"] +[ext_resource type="Script" path="res://src/infra/repos/local/reservation.gd" id="5_50dbn"] + +[node name="Main" type="Control"] +layout_mode = 3 +anchor_left = 0.02 +anchor_top = 0.01 +anchor_right = 0.98 +anchor_bottom = 0.99 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_vo4ao") + +[node name="BackgroundColor" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.133333, 0.14902, 0.176471, 1) + +[node name="Pages" type="Control" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Board" parent="Pages" instance=ExtResource("2_brvql")] +layout_mode = 1 +anchors_preset = 15 +anchor_bottom = 1.0 +offset_bottom = 0.0 +grow_vertical = 2 + +[node name="ReservationCreation" parent="Pages" instance=ExtResource("3_qr4p2")] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_bottom = 1.0 +offset_bottom = 0.0 +grow_vertical = 2 + +[node name="TimeSetting" parent="Pages" instance=ExtResource("4_popa2")] +visible = false +layout_mode = 1 + +[node name="Repos" type="Node" parent="."] + +[node name="Reservation" type="Node" parent="Repos"] +script = ExtResource("5_50dbn") diff --git a/scenes/reservation/reservation_creation.gd b/scenes/reservation/reservation_creation.gd new file mode 100644 index 0000000..ecde03c --- /dev/null +++ b/scenes/reservation/reservation_creation.gd @@ -0,0 +1,115 @@ +extends VBoxContainer + +@onready var _main: Main = get_tree().get_current_scene() +@onready var _back_button := $TopBar/BackButton +@onready var _apply_button := $TopBar/ApplyButton + +@onready var _title_field := $TitleField +@onready var _date_field := $DateField +@onready var _start_time_field := $StartTimeField +@onready var _finish_time_field := $FinishTimeField +@onready var _creator_field := $CreatorField +@onready var _room_field := $RoomField +@onready var _description_field := $DescriptionField + +func _ready(): + initialize_signals() + +func initialize_signals(): + _back_button.pressed.connect(_on_back_button_pressed) + _apply_button.pressed.connect(_on_apply_button_pressed) + +func _on_back_button_pressed(): + _main.load_page(Main.Pages.Board) + +func _on_apply_button_pressed(): + _create_reservation() + +func _create_reservation(): + if not _fields_are_correct(): + return + + var dto = CreateReservationDTO.new() + dto.title = _title_field.get_value() + dto.date = _date_field.get_value() + dto.start_time = _start_time_field.get_value() + dto.finish_time = _finish_time_field.get_value() + dto.creator = _creator_field.get_value() + dto.room_id = _room_field.get_value() # TODO: make it listbox + dto.description = _description_field.get_value() + dto.color = randi_range(1, 3) + + var repo = _main.get_reservation_repo() + repo.create_reservation(dto) + + dto.queue_free() + + _main.load_page(Main.Pages.Board) + clean() + +func _fields_are_correct(): + var successful := true + + if len(_title_field.get_value()) < 1: + print("The title is not entered.") + successful = false + + if not _time_is_correct(): + successful = false + + return successful + +func _time_is_correct(): + var start_time = _start_time_field.get_value() + var finish_time = _finish_time_field.get_value() + + var start_time_is_after_finish_time = \ + start_time["hours"] > finish_time["hours"] or \ + (start_time["hours"] == finish_time["hours"] and \ + start_time["minutes"] >= finish_time["minutes"]) + + if start_time_is_after_finish_time: + print("Start time should not be more than or equal to finish time.") + return false + + var repo = _main.get_reservation_repo() + var reservations = repo.list_reservations() + + var new_start_time_minutes = start_time["hours"]*60 + start_time["minutes"] + var new_finish_time_minutes = finish_time["hours"]*60 + finish_time["minutes"] + + for reservation in reservations: + var other_start_time = reservation.start_time + var other_finish_time = reservation.finish_time + var other_start_time_minutes = other_start_time["hours"]*60 + other_start_time["minutes"] + var other_finish_time_minutes = other_finish_time["hours"]*60 + other_finish_time["minutes"] + + var is_busy = ( + ( + new_start_time_minutes >= other_start_time_minutes and + new_start_time_minutes < other_finish_time_minutes + ) or ( + new_finish_time_minutes > other_start_time_minutes and + new_finish_time_minutes <= other_finish_time_minutes + ) or ( + new_start_time_minutes >= other_start_time_minutes and + new_finish_time_minutes <= other_finish_time_minutes + ) or ( + new_start_time_minutes <= other_start_time_minutes and + new_finish_time_minutes >= other_finish_time_minutes + ) + ) + + if is_busy: + print("The selected time slot is busy.") + return false + + return true + +func update(): + _ready() + +func clean(): + _title_field.clean() + _start_time_field.clean() + _finish_time_field.clean() diff --git a/scenes/reservation/reservation_creation.tscn b/scenes/reservation/reservation_creation.tscn new file mode 100644 index 0000000..23a34e7 --- /dev/null +++ b/scenes/reservation/reservation_creation.tscn @@ -0,0 +1,99 @@ +[gd_scene load_steps=6 format=3 uid="uid://csfn8q6b5hj4y"] + +[ext_resource type="Theme" uid="uid://cmhwbyqu6nh38" path="res://assets/themes/big.tres" id="1_j1bkw"] +[ext_resource type="Script" path="res://scenes/reservation/reservation_creation.gd" id="1_whumk"] +[ext_resource type="PackedScene" uid="uid://d0fdiesiaajlq" path="res://scenes/common/edit_field.tscn" id="2_qfs8j"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dlqbv"] +bg_color = Color(0.6, 0.6, 0.6, 0) +border_width_top = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_yafv8"] +bg_color = Color(0.6, 0.6, 0.6, 0) +border_width_top = 3 +border_color = Color(0.8, 0.8, 0.8, 0.392157) + +[node name="ReservationCreation" type="VBoxContainer"] +anchors_preset = 10 +anchor_right = 1.0 +offset_bottom = 23.0 +grow_horizontal = 2 +theme_override_constants/separation = 35 +script = ExtResource("1_whumk") + +[node name="TopBar" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="BackButton" type="Button" parent="TopBar"] +custom_minimum_size = Vector2(0, 100) +layout_mode = 2 +theme = ExtResource("1_j1bkw") +text = "Назад" + +[node name="Label" type="Label" parent="TopBar"] +layout_mode = 2 +size_flags_horizontal = 6 +theme = ExtResource("1_j1bkw") +theme_override_colors/font_shadow_color = Color(0, 0, 0, 1) +theme_override_constants/shadow_offset_x = 3 +theme_override_constants/shadow_offset_y = 3 +text = "Бронирование комнаты" +horizontal_alignment = 1 + +[node name="ApplyButton" type="Button" parent="TopBar"] +custom_minimum_size = Vector2(0, 100) +layout_mode = 2 +theme = ExtResource("1_j1bkw") +text = "Создать" + +[node name="Splitter" type="Panel" parent="."] +custom_minimum_size = Vector2(0, 15) +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_dlqbv") + +[node name="TitleField" parent="." instance=ExtResource("2_qfs8j")] +layout_mode = 2 +title = "Название" + +[node name="Splitter2" type="Panel" parent="."] +custom_minimum_size = Vector2(0, 5) +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_yafv8") + +[node name="DateField" parent="." instance=ExtResource("2_qfs8j")] +layout_mode = 2 +title = "Дата" +type = 2 + +[node name="StartTimeField" parent="." instance=ExtResource("2_qfs8j")] +layout_mode = 2 +title = "Начало" +type = 3 + +[node name="FinishTimeField" parent="." instance=ExtResource("2_qfs8j")] +layout_mode = 2 +title = "Конец" +type = 3 + +[node name="Splitter3" type="Panel" parent="."] +custom_minimum_size = Vector2(0, 5) +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_yafv8") + +[node name="CreatorField" parent="." instance=ExtResource("2_qfs8j")] +layout_mode = 2 +title = "Создатель" + +[node name="RoomField" parent="." instance=ExtResource("2_qfs8j")] +layout_mode = 2 +title = "Комната" + +[node name="Splitter4" type="Panel" parent="."] +custom_minimum_size = Vector2(0, 5) +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_yafv8") + +[node name="DescriptionField" parent="." instance=ExtResource("2_qfs8j")] +layout_mode = 2 +title = "Описание" +type = 1 diff --git a/scenes/reservation/reservation_creation_window.tscn b/scenes/reservation/reservation_creation_window.tscn new file mode 100644 index 0000000..5d34ba7 --- /dev/null +++ b/scenes/reservation/reservation_creation_window.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=2 format=3 uid="uid://dcwvxdme8mjsq"] + +[ext_resource type="PackedScene" uid="uid://csfn8q6b5hj4y" path="res://scenes/reservation/reservation_creation.tscn" id="1_yk1ll"] + +[node name="ReservationCreation" type="Control"] +layout_mode = 3 +anchor_left = 0.02 +anchor_top = 0.01 +anchor_right = 0.98 +anchor_bottom = 0.99 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="BackgroundColor" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.133333, 0.14902, 0.176471, 1) + +[node name="VerticalBar" parent="." instance=ExtResource("1_yk1ll")] +layout_mode = 0 +anchors_preset = 0 +anchor_right = 0.0 +grow_horizontal = 1 diff --git a/src/domain/entities/reservation.gd b/src/domain/entities/reservation.gd new file mode 100644 index 0000000..43b5268 --- /dev/null +++ b/src/domain/entities/reservation.gd @@ -0,0 +1,20 @@ +extends Node +class_name ReservationEntity + +var id: String + +@export var title: String + +@export var description: String + +@export var room_id: String + +@export var creator: String + +@export var date: String + +@export var start_time: Dictionary # TODO: get rid of dictionaries if can + +@export var finish_time: Dictionary + +@export var color: int diff --git a/src/infra/dtos/reservation/create.gd b/src/infra/dtos/reservation/create.gd new file mode 100644 index 0000000..dd00c42 --- /dev/null +++ b/src/infra/dtos/reservation/create.gd @@ -0,0 +1,18 @@ +extends Node +class_name CreateReservationDTO + +var title: String + +var description: String + +var room_id: String + +var creator: String + +var date: String + +var start_time: Dictionary # TODO: get rid of dictionaries if can + +var finish_time: Dictionary + +var color: int diff --git a/src/infra/dtos/reservation/update.gd b/src/infra/dtos/reservation/update.gd new file mode 100644 index 0000000..708a6f8 --- /dev/null +++ b/src/infra/dtos/reservation/update.gd @@ -0,0 +1,18 @@ +extends Node +class_name UpdateReservationDTO + +@export var title: String + +@export var description: String + +@export var room_id: String + +@export var creator: String + +@export var date: String + +@export var start_time: Dictionary # TODO: get rid of dictionaries if can + +@export var finish_time: Dictionary + +@export var color: int diff --git a/src/infra/repos/abstract/reservation.gd b/src/infra/repos/abstract/reservation.gd new file mode 100644 index 0000000..3e07fe5 --- /dev/null +++ b/src/infra/repos/abstract/reservation.gd @@ -0,0 +1,25 @@ +extends Node +class_name AbstractReservationRepo + +var _current_reservation = null + +func create_reservation(dto: CreateReservationDTO): + pass + +func cancel_reservation(reservation_id): + pass + +func change_reservation(reservation_id, dto: UpdateReservationDTO): + pass + +func get_reservation(reservation_id): + pass + +func list_reservations(): + pass + +func set_current_reservation(value): + _current_reservation = value + +func get_current_reservation(value): + return _current_reservation diff --git a/src/infra/repos/local/reservation.gd b/src/infra/repos/local/reservation.gd new file mode 100644 index 0000000..e492307 --- /dev/null +++ b/src/infra/repos/local/reservation.gd @@ -0,0 +1,54 @@ +extends AbstractReservationRepo +class_name LocalReservationRepo + +const uuid_util = preload('res://addons/uuid/uuid.gd') + +var _reservations = {} + +func create_reservation(dto: CreateReservationDTO): + var entity = ReservationEntity.new() + + entity.id = uuid_util.v4() + entity.title = dto.title + entity.description = dto.description + entity.room_id = dto.room_id + entity.creator = dto.creator + entity.date = dto.date + entity.start_time = dto.start_time.duplicate(true) + entity.finish_time = dto.finish_time.duplicate(true) + entity.color = dto.color + + _reservations[entity.id] = entity + +func cancel_reservation(reservation_id): + _reservations[reservation_id].queue_free() + _reservations.erase(reservation_id) + +func change_reservation(reservation_id, dto: UpdateReservationDTO): + var entity = _reservations[reservation_id] + + entity.title = dto.title + entity.description = dto.description + entity.room_id = dto.room_id + entity.creator = dto.creator + entity.start_date = dto.start_date.duplicate(true) + entity.finish_date = dto.finish_date.duplicate(true) + +func get_reservation(reservation_id): + return _reservations[reservation_id] + +func list_reservations(): + var reservations = [] + + for key in _reservations: + reservations.append(_reservations[key]) + + reservations.sort_custom(self._compare_reservations_by_start_time) + + return reservations + +func _compare_reservations_by_start_time(a: ReservationEntity, b: ReservationEntity) -> int: + var time_a = a.start_time["hours"] * 60 + a.start_time["minutes"] + var time_b = b.start_time["hours"] * 60 + b.start_time["minutes"] + + return time_a < time_b