diff --git a/src/pilgrim/ui/screens/diary_settings_screen.py b/src/pilgrim/ui/screens/diary_settings_screen.py new file mode 100644 index 0000000..7b84e1a --- /dev/null +++ b/src/pilgrim/ui/screens/diary_settings_screen.py @@ -0,0 +1,176 @@ + +from textual.widgets import Static +from textual.containers import Container +from textual.widgets import Header, Footer, Label, Button,Checkbox,Input +from textual.screen import Screen +from textual.reactive import reactive +from textual.binding import Binding +from textual import on + +from pilgrim import TravelDiary +from pilgrim.ui.screens.modals.delete_all_entries_from_diary_modal import DeleteAllEntriesModal +from pilgrim.ui.screens.modals.delete_all_photos_from_diary_modal import DeleteAllPhotosModal +from pilgrim.ui.screens.modals.delete_diary_modal import DeleteDiaryModal + + +class SettingsScreen(Screen): + is_changed = reactive(False) + BINDINGS = [ + Binding("escape","cancel","Cancel"), + ] + + def __init__(self,diary:TravelDiary): + super().__init__() + self.current_diary = diary + + self.header = Header() + self.footer = Footer() + self.title = "Settings" + + self.diary_name = Static(self.current_diary.name,id="DiarySettingsScreen-DiaryName") + self.is_the_diary_set_to_auto_open = False + self.diary_entry_count = Static("0") + self.diary_photo_count = Static("0") + self.save_button = Button("Save") + self.cancel_button = Button("Cancel",id="DiarySettingsScreen-cancel_button") + self.apply_button = Button("Apply") + self.backup_diary_button = Button("Backup Diary") + self.delete_diary_button = Button("Delete Diary",id="DiarySettingsScreen-DeleteDiaryButton") + self.delete_all_entries_button = Button("Delete All Entries",id="DiarySettingsScreen-DeleteAllEntriesButton") + self.delete_all_photos_button = Button("Delete All Photos",id="DiarySettingsScreen-DeleteAllPhotosButton") + self.set_auto_open_to_this_diary = Checkbox(id="set_auto_open_to_this_diary",value=self.is_the_diary_set_to_auto_open) + self.delete_diary_button_container = Container( + Label("Delete Diary:"), + + self.delete_diary_button, + id="DiarySettingsScreen-DeleteDiaryButtonContainer", + classes="DiarySettingsScreen-DeleteDiaryButtonContainer Button_Container" + ) + self.backup_diary_button_container = Container( + Label("Backup Diary:"), + self.backup_diary_button, + id="DiarySettingsScreen-BackupDiaryButtonContainer", + classes="DiarySettingsScreen-BackupDiaryButtonContainer Button_Container" + ) + self.delete_all_entries_button_container = Container( + Label("Delete All Entries:"), + self.delete_all_entries_button, + + id="DiarySettingsScreen-DeleteAllEntriesButtonContainer", + classes="DiarySettingsScreen-DeleteAllEntriesButtonContainer Button_Container" + ) + self.delete_all_photos_button_container = Container( + Label("Delete All Photos:"), + self.delete_all_photos_button, + + + id="DiarySettingsScreen-DeleteAllPhotosButtonContainer", + classes="DiarySettingsScreen-DeleteAllPhotosButtonContainer Button_Container" + ) + self.diary_name_container = Container( + Label("Diary Name:"), + self.diary_name, + id="DiarySettingsScreen-DiaryNameContainer", + classes="DiarySettingsScreen-DiaryNameContainer Data_Container" + + ) + self.diary_entry_count_container = Container( + Label("Diary Entries:"), + self.diary_entry_count, + id="DiarySettingsScreen-DiaryEntryCountContainer", + classes="DiarySettingsScreen-DiaryEntryCountContainer Data_Container" + ) + self.set_auto_open_to_this_diary_container = Container( + Label("Set Open This Diary On App Start?:"), + self.set_auto_open_to_this_diary, + id="DiarySettingsScreen-SetAutoOpenToThisDiaryContainer", + classes="DiarySettingsScreen-SetAutoOpenToThisDiaryContainer Data_Container" + + ) + self.diary_photo_count_container = Container( + Label("Diary Photos:"), + self.diary_photo_count, + id="DiarySettingsScreen-DiaryPhotoCountContainer", + classes="DiarySettingsScreen-DiaryPhotoCountContainer Data_Container" + ) + + self.diary_info_container = Container( + + self.diary_name_container, + self.diary_entry_count_container, + self.diary_photo_count_container, + self.set_auto_open_to_this_diary_container, + id="DiarySettingsScreen-DiaryInfoContainer", + classes="DiarySettingsScreen-DiaryInfoContainer", + ) + + self.diary_denger_zone_container = Container( + self.backup_diary_button_container, + self.delete_diary_button_container, + self.delete_all_entries_button_container, + self.delete_all_photos_button_container, + id="DiarySettingsScreen-DiaryDengerZoneContainer", + classes="DiarySettingsScreen-DiaryDengerZoneContainer" + ) + self.button_container = Container( + self.save_button, + self.apply_button, + self.cancel_button, + id="DiarySettingsScreen-ButtonContainer", + classes="DiarySettingsScreen-ButtonContainer" + ) + self.main = Container( + self.diary_info_container, + self.diary_denger_zone_container, + self.button_container, + id="DiarySettingsScreen-MainContainer", + classes="DiarySettingsScreen-MainContainer" + ) + self.diary_info_container.border_title = "Diary Info" + self.diary_denger_zone_container.border_title = "Denger Zone" + + @on(Checkbox.Changed, "#set_auto_open_to_this_diary") + def on_checkbox_changed(self, event): + self.is_changed = not self.is_changed + self.notify("Checkboxed") + + @on(Button.Pressed, "#DiarySettingsScreen-cancel_button") + def on_cancel_button_pressed(self, event): + self.action_cancel() + + @on(Button.Pressed, "#DiarySettingsScreen-DeleteDiaryButton") + def on_delete_diary_button_pressed(self, event): + self.app.push_screen(DeleteDiaryModal(diary_id=self.current_diary.id,diary_name=self.current_diary.name)) + + @on(Button.Pressed, "#DiarySettingsScreen-DeleteAllEntriesButton") + def on_delete_all_entries_button_pressed(self, event): + self.app.push_screen(DeleteAllEntriesModal(diary_id=self.current_diary.id)) + + @on(Button.Pressed, "#DiarySettingsScreen-DeleteAllPhotosButton") + def on_delete_all_photos_button_pressed(self, event): + self.app.push_screen(DeleteAllPhotosModal(diary_id=self.current_diary.id)) + + def action_cancel(self): + if self.is_changed: + self.notify("Cancel button pressed, but changes are not saved",severity="error") + return + self.app.exit() + + + def watch_is_changed(self, value): + label = self.set_auto_open_to_this_diary_container.query_one(Label) + if value: + label.add_class("DiarySettingsScreen-SetAutoOpenToThisDiaryContainer-Not-Saved-Label") + else: + label.remove_class("DiarySettingsScreen-SetAutoOpenToThisDiaryContainer-Not-Saved-Label") + + def compose(self): + yield Header() + yield self.main + yield Footer() + + def on_mount(self): + pass + + def set_checkbox_state(self): + self.set_auto_open_to_this_diary.value = True \ No newline at end of file diff --git a/src/pilgrim/ui/screens/modals/delete_all_entries_from_diary_modal.py b/src/pilgrim/ui/screens/modals/delete_all_entries_from_diary_modal.py new file mode 100644 index 0000000..ec5d5ad --- /dev/null +++ b/src/pilgrim/ui/screens/modals/delete_all_entries_from_diary_modal.py @@ -0,0 +1,20 @@ + +from textual.widgets import Button + +from textual import on + +from pilgrim.ui.screens.modals.delete_yes_confirmation_modal import DeleteYesConfirmationModal + + +class DeleteAllEntriesModal(DeleteYesConfirmationModal): + def __init__(self,diary_id:int): + super().__init__(diary_id) + self.head_text.update("Are you sure you want to delete all entries from this diary?") + + + + @on(Button.Pressed, "#DeleteDiaryModal-DeleteButton") + def on_delete_button_pressed(self, event): + self.result = True + self.dismiss() + diff --git a/src/pilgrim/ui/screens/modals/delete_all_photos_from_diary_modal.py b/src/pilgrim/ui/screens/modals/delete_all_photos_from_diary_modal.py new file mode 100644 index 0000000..d34b8bb --- /dev/null +++ b/src/pilgrim/ui/screens/modals/delete_all_photos_from_diary_modal.py @@ -0,0 +1,20 @@ + +from textual.widgets import Button + +from textual import on + +from pilgrim.ui.screens.modals.delete_yes_confirmation_modal import DeleteYesConfirmationModal + + +class DeleteAllPhotosModal(DeleteYesConfirmationModal): + def __init__(self,diary_id:int): + super().__init__(diary_id) + self.head_text.update("Are you sure you want to delete all photos from this diary?") + + + + @on(Button.Pressed, "#DeleteDiaryModal-DeleteButton") + def on_delete_button_pressed(self, event): + self.result = True + self.dismiss() + diff --git a/src/pilgrim/ui/screens/modals/delete_diary_modal.py b/src/pilgrim/ui/screens/modals/delete_diary_modal.py new file mode 100644 index 0000000..61e6597 --- /dev/null +++ b/src/pilgrim/ui/screens/modals/delete_diary_modal.py @@ -0,0 +1,59 @@ +from textual.containers import Container +from textual.widgets import Header, Footer, Label, Button,Input +from textual.screen import Screen +from textual.binding import Binding +from textual import on + + +class DeleteDiaryModal(Screen): + + BINDINGS = [ + Binding("escape","cancel","Cancel"), + ] + def __init__(self, diary_id: int,diary_name:str): + super().__init__() + self.diary_id = diary_id + self.diary_name = diary_name + self.user_input = Input(placeholder=f"Type diary name to confirm: ({self.diary_name})",id="DeleteDiaryModal-UserInput") + self.delete_button = Button("Delete Diary",id="DeleteDiaryModal-DeleteButton",disabled=True) + self.cancel_button = Button("Cancel",id="DeleteDiaryModal-CancelButton") + self.result = None + + def compose(self): + yield Header() + yield Container( + Label("Are you sure you want to delete this diary?"), + self.user_input, + Container( + self.delete_button, + self.cancel_button, + id="DeleteDiaryModal-ButtonContainer", + classes="DeleteDiaryModal-ButtonContainer" + ), + id="DeleteDiaryModal-MainContainer", + classes="DeleteDiaryModal-MainContainer" + ) + yield Footer() + + @on(Input.Changed,"#DeleteDiaryModal-UserInput") + def on_user_input_changed(self, event): + input_text = event.value.strip() + + if input_text == self.diary_name: + self.delete_button.disabled = False + else: + self.delete_button.disabled = True + + @on(Button.Pressed,"#DeleteDiaryModal-DeleteButton") + def on_delete_button_pressed(self, event): + self.result = True + self.dismiss() + + + @on(Button.Pressed,"#DeleteDiaryModal-CancelButton") + def on_cancel_button_pressed(self, event): + self.action_cancel() + + + def action_cancel(self): + self.dismiss() diff --git a/src/pilgrim/ui/screens/modals/delete_yes_confirmation_modal.py b/src/pilgrim/ui/screens/modals/delete_yes_confirmation_modal.py new file mode 100644 index 0000000..8c6c9bf --- /dev/null +++ b/src/pilgrim/ui/screens/modals/delete_yes_confirmation_modal.py @@ -0,0 +1,54 @@ +from textual.containers import Container +from textual.widgets import Header, Footer, Label, Button,Input +from textual.screen import Screen +from textual.binding import Binding +from textual import on + + +class DeleteYesConfirmationModal(Screen): + BINDINGS = [ + Binding("escape", "cancel", "Cancel"), + ] + def __init__(self,diary_id:int): + super().__init__() + self.diary_id = diary_id + self.user_input = Input(placeholder="Type 'Yes, I do ' to confirm",id="DeleteYesConfirmationModal-UserInput") + self.delete_button = Button("Delete",id="DeleteYesConfirmationModal-DeleteButton",disabled=True) + self.cancel_button = Button("Cancel",id="DeleteYesConfirmationModal-CancelButton") + self.head_text = Label("Are you sure you want to delete this diary?",id="DeleteYesConfirmationModal-HeadText") + self.second_head_text = Label("This action cannot be undone.",id="DeleteYesConfirmationModal-SecondHeadText") + self.delete_modal_container = Container( + self.head_text, + self.second_head_text, + self.user_input, + Container( + self.delete_button, + self.cancel_button, + id="DeleteYesConfirmationModal-DeleteButtonContainer", + classes="DeleteYesConfirmationModal-DeleteButtonContainer" + ), + id="DeleteYesConfirmationModal-DeleteModalContainer", + classes="DeleteYesConfirmationModal-DeleteModalContainer" + ) + self.result = None + + @on(Input.Changed,"#DeleteYesConfirmationModal-UserInput") + def on_user_input_changed(self, event): + input_text = event.value.strip() + if input_text == "Yes, I do": + self.delete_button.disabled = False + else: + self.delete_button.disabled = True + + @on(Button.Pressed,"#DeleteYesConfirmationModal-CancelButton") + def on_cancel_button_pressed(self, event): + self.action_cancel() + + def action_cancel(self): + self.dismiss() + self.app.push_screen(SettingsScreen(diary=travel_diary[0])) + + def compose(self): + yield Header() + yield Footer() + yield self.delete_modal_container \ No newline at end of file diff --git a/src/pilgrim/ui/styles/pilgrim.css b/src/pilgrim/ui/styles/pilgrim.css index 5b9bf3b..8486ac0 100644 --- a/src/pilgrim/ui/styles/pilgrim.css +++ b/src/pilgrim/ui/styles/pilgrim.css @@ -1,7 +1,8 @@ Screen { layout: vertical; - background: $surface-darken-1; + background: $primary-background-darken-3; align: center middle; + hatch: right $secondary-background-darken-3; } .EditEntryScreen-sub-header { @@ -623,4 +624,265 @@ Screen.-modal { .ConfirmDeleteModal-Button { margin: 0 1; width: 1fr; +} + +.DeleteYesConfirmationModal-DeleteModalContainer, +.DeleteDiaryModal-MainContainer { + align: center middle; + layout: vertical; + margin: 2; + padding: 2; + background: $primary-background; + height: auto; + width: auto; + min-width: 80%; + max-width: 95%; + border: solid $primary; +} + +/* Labels de texto */ +.DeleteYesConfirmationModal-DeleteModalContainer > Label, +.DeleteDiaryModal-MainContainer > Label { + margin: 1 0; + padding: 0 1; + color: $error; + text-align: center; + width: 100%; +} + +/* Input fields */ +.DeleteYesConfirmationModal-DeleteModalContainer > Input, +.DeleteDiaryModal-MainContainer > Input { + margin: 1 0; + width: 100%; + height: 3; +} + +/* Container dos botões */ +.DeleteYesConfirmationModal-DeleteButtonContainer, +.DeleteDiaryModal-ButtonContainer { + layout: horizontal; + align: center middle; + margin: 2 0 0 0; + height: auto; + width: 100%; + padding: 0; +} + +/* Botões individuais */ +.DeleteYesConfirmationModal-DeleteButtonContainer > Button, +.DeleteDiaryModal-ButtonContainer > Button { + width: 45%; + margin: 0 1; + height: 3; +} + +/* Botão de delete (primeiro botão) */ +.DeleteYesConfirmationModal-DeleteButtonContainer > Button:first-child, +.DeleteDiaryModal-ButtonContainer > Button:first-child { + background: $error-darken-1; +} + +/* Botão de cancel */ +.DeleteYesConfirmationModal-DeleteButtonContainer > Button:last-child, +.DeleteDiaryModal-ButtonContainer > Button:last-child { + background: $surface; +} + +/* Estados disabled para botões de delete */ +.DeleteYesConfirmationModal-DeleteButtonContainer > Button:first-child:disabled, +.DeleteDiaryModal-ButtonContainer > Button:first-child:disabled { + background: $surface-lighten-1; + color: $text-muted; +} + +/* Espaçamento específico para labels secundários */ +#DeleteYesConfirmationModal-SecondHeadText { + margin: 1 0; + padding: 0 1; + color: $warning; + text-align: center; + text-style: italic; +} + + + + +.Data_Container{ + width: 100%; + layout: grid; + grid-size: 2 1; /* 2 colunas, 1 linha */ + height:auto; + + +} + +.Button_Container{ + width: 100%; + layout: grid; + grid-size: 2 2; + height: auto; + + +} + + +.DiarySettingsScreen-DeleteDiaryButtonContainer{ + grid-size: 2 1; + padding: 0 1; + content-align: center middle; + padding-bottom:1; + +} + +.DiarySettingsScreen-DeleteAllEntriesButtonContainer{ + + margin:0; + padding: 0 1; + height:auto; + padding-bottom:1; + + +} + +.DiarySettingsScreen-DeleteAllPhotosButtonContainer{ + margin:0; + padding: 0 1; + height:auto; + padding-bottom:1; + +} +.DiarySettingsScreen-DeleteAllPhotosButtonContainer > Label, +.DiarySettingsScreen-DeleteAllEntriesButtonContainer > Label{ +color: $error-lighten-3; +padding:1; + +} + +.DiarySettingsScreen-BackupDiaryButtonContainer{ +margin:0; +padding:0 1; +padding-bottom:1 + +} + +.DiarySettingsScreen-BackupDiaryButtonContainer > Label{ +padding:1; +color: $success-darken-1; +} + +.DiarySettingsScreen-BackupDiaryButtonContainer > Button{ + background: $success; +} + +.DiarySettingsScreen-DeleteDiaryButtonContainer > Label{ + color: $error-lighten-3; + content-align: left middle; + padding:1 + + + +} + +.DiarySettingsScreen-DeleteAllPhotosButtonContainer > Button, +.DiarySettingsScreen-DeleteAllEntriesButtonContainer > Button, +.DiarySettingsScreen-DeleteDiaryButtonContainer Button{ + + background: $error; + + } + +.DiarySettingsScreen-MainContainer{ + + align: center top; + layout: vertical; + margin:1; + padding:1; + background: $primary-background + + +} + +.DiarySettingsScreen-DiaryInfoContainer{ + + padding:1 2; + border:round grey; + height:auto; + width: 90%; + padding-bottom: 0; +} + +.DiarySettingsScreen-ButtonContainer{ + height:auto; + layout: grid; + grid-size: 3 1; + grid-gutter:2; + dock:bottom; +} + +.DiarySettingsScreen-ButtonContainer > Button:first-child { + + margin-left:2 + +} + +.DiarySettingsScreen-ButtonContainer > Button:last-child { + + margin-right:2 + +} + +.DiarySettingsScreen-ButtonContainer > Button { + width: 100%; + + + +} + + +#DiarySettingsScreen-DiaryPhotoCountContainer > Static:first-child, +#DiarySettingsScreen-DiaryEntryCountContainer > Static:first-child, +#DiarySettingsScreen-DiaryNameContainer > Static:first-child{ + + text-align: left; + + padding: 0 1; + padding-bottom:1 + +} + + + +#DiarySettingsScreen-DiaryPhotoCountContainer > Static:last-child, +#DiarySettingsScreen-DiaryEntryCountContainer > Static:last-child, +#DiarySettingsScreen-DiaryNameContainer > Static:last-child{ + + text-align: right; + padding:0 1 + +} + +.DiarySettingsScreen-SetAutoOpenToThisDiaryContainer > Checkbox{ + + margin:0; + padding:1; + background: $primary-background; + border:none; + + + +} + +.DiarySettingsScreen-SetAutoOpenToThisDiaryContainer-Not-Saved-Label{ + text-style:bold; + color:$warning-lighten-2; + +} + +.DiarySettingsScreen-DiaryDengerZoneContainer{ + border: round $error-darken-1; + width: 90%; + padding: 0 1; + height: auto; + padding-bottom: 0; } \ No newline at end of file