diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index de9ccfdb..dfa7f7a1 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -70,6 +70,24 @@ "edit_game_modal_icon_resolution": "Resolución recomendada: 256x256px", "edit_game_modal_logo_resolution": "Resolución recomendada: 640x360px", "edit_game_modal_hero_resolution": "Resolución recomendada: 1920x620px", + "cancel": "Cancelar", + "confirm": "Confirmar", + "decky_plugin_installation_error": "Error instalando plugin Decky: {{error}}", + "decky_plugin_installation_failed": "Falló instalar plugin Decky: {{error}}", + "decky_plugin_installed": "Plugin Decky v{{version}} instalanda exitosamente", + "decky_plugin_installed_version": "Plugin Decky (v{{version}})", + "edit_game_modal_drop_hero_image_here": "Soltá la imagen hero acá", + "edit_game_modal_drop_icon_image_here": "Soltá la imagen de ícono hero acá", + "edit_game_modal_drop_logo_image_here": "Soltá la imagen de logo hero acá", + "edit_game_modal_drop_to_replace_hero": "Soltá para reemplazar hero", + "edit_game_modal_drop_to_replace_icon": "Soltá para reemplazar el ícono", + "edit_game_modal_drop_to_replace_logo": "Soltá para reemplazar el logo", + "install_decky_plugin": "Instalar plugin Decky", + "install_decky_plugin_message": "Esto va a descargar e instalar el plugin de Decky Loader para Hydra. Esto quizás requierea permisos elevados, ¿querés continuar?", + "install_decky_plugin_title": "Instarlar el plugin Decky Hydra", + "update_decky_plugin": "Actualizar plugin Decky", + "update_decky_plugin_message": "Una nueva versión del plugin Decky para Hydra está disponible. ¿Querés actualizarlo ahora?", + "update_decky_plugin_title": "Actualizar plugin Decky para Hydra", "edit_game_modal_assets": "Recursos" }, "header": { @@ -285,6 +303,62 @@ "keyshop_price": "Precio de tiendas de terceros", "historical_retail": "Precio de tiendas", "historical_keyshop": "Precio de tiendas de terceros", + "add_to_favorites": "Añadir a favoritos", + "be_first_to_review": "¡Sé la primera persona en compartir lo que pensas de este juego!", + "create_shortcut_simple": "Crear atajo", + "delete_review": "Eliminar reseña", + "delete_review_modal_cancel_button": "Cancelar", + "delete_review_modal_delete_button": "Eliminar", + "delete_review_modal_description": "Esta acción no se puede deshacer.", + "delete_review_modal_title": "¿De verdad querés eliminar esta reseña?", + "failed_remove_files": "Error al eliminar los archivos", + "failed_remove_from_library": "Error al eliminar de la librería", + "failed_update_favorites": "Error al actualizar favoritos", + "files_removed_success": "Archivos eliminados correctamente", + "filter_by_source": "Filtrar por fuente", + "game_removed_from_library": "Juego eliminado de la librería", + "hide_original": "Ocultar original", + "leave_a_review": "Crear una reseña", + "load_more_reviews": "Cargar más reseñas", + "loading_more_reviews": "Cargando más reseñas...", + "loading_reviews": "Cargando reseñas...", + "maybe_later": "Tal vez después", + "no_repacks_found": "Sin fuentes encontradas para este juego", + "no_reviews_yet": "Sin reseñas aún", + "properties": "Propiedades", + "rating": "Calificación", + "rating_count": "Calificación", + "rating_negative": "Negativa", + "rating_neutral": "Neutral", + "rating_positive": "Positiva", + "rating_stats": "Calificación", + "rating_very_negative": "Muy Negativa", + "rating_very_positive": "Muy Positiva", + "remove_from_favorites": "Eliminar de favoritos", + "remove_review": "Eliminar reseña", + "review_cannot_be_empty": "El campo de la reseña no puede estar vacío.", + "review_deleted_successfully": "Reseña eliminada exitosamente.", + "review_deletion_failed": "Error al eliminar reseña. Por favor intentá de nuevo.", + "review_submission_failed": "Error al subir reseña. Por favor intentá de nuevo.", + "review_submitted_successfully": "¡Reseña eliminada exitosamente!", + "reviews": "Reseñas", + "show_less": "Ver menos", + "show_more": "Ver más", + "show_original": "Ver original", + "show_original_translated_from": "Ver original (traducido del {{language}})", + "show_translation": "Ver traducción", + "sort_highest_score": "Puntuación más alta", + "sort_lowest_score": "Puntuación más baja", + "sort_most_voted": "Más votads", + "sort_newest": "Más nuevos", + "sort_oldest": "Más viejos", + "submit_review": "Enviar", + "submitting": "Subiendo...", + "vote_failed": "Error al registrar tu voto. Por favor intentá de nuevo.", + "would_you_recommend_this_game": "¿Querés escribir una reseña para este juego?", + "write_review_placeholder": "Compartí tus pensamientos sobre este juego...", + "yes": "Si", + "you_seemed_to_enjoy_this_game": "Parece que has disfrutado de este juego", "language": "Idioma", "caption": "Subtítulo", "audio": "Audio" @@ -345,7 +419,7 @@ "enable_real_debrid": "Habilitar Real-Debrid", "real_debrid_description": "Real-Debrid es un descargador que te permite descargar archivos más rápidos, solo límitado por la velocidad de tu internet.", "debrid_invalid_token": "Token API inválido", - "debrid_api_token_hint": "Podés obtener la el token de tu API <0>acá", + "debrid_api_token_hint": "Podés obtener el token de tu API <0>acá", "real_debrid_free_account_error": "La cuenta \"{{username}}\" es una cuenta gratis. Por favor suscribíte a Real-Debrid", "debrid_linked_message": "Cuenta \"{{username}}\" vinculada", "save_changes": "Guardar cambios", @@ -357,7 +431,7 @@ "download_count_zero": "Sin opciones de descarga", "download_count_one": "{{countFormatted}} opción de descarga", "download_count_other": "{{countFormatted}} opciones de descarga", - "download_source_url": "Descargar fuente URL", + "download_source_url": "Añadir URL de una fuente", "add_download_source_description": "Introducí la URL del archivo .json", "download_source_up_to_date": "Actualizado", "download_source_errored": "Error", @@ -409,7 +483,7 @@ "subscription_renew_cancelled": "Renovación automática desactivada", "subscription_renews_on": "Tu suscripción se renueva el {{date}}", "bill_sent_until": "Tu próxima factura se enviará este día", - "no_themes": "Parece que no tenés ningún tema aún, pero no te preocupés, presiona acá para hacer tu primera obra maestra.", + "no_themes": "Parece que no tenés ningún tema aún, pero no te preocupes, presiona acá para hacer tu primera obra maestra.", "editor_tab_code": "Código", "editor_tab_info": "Info", "editor_tab_save": "Guardar", @@ -443,7 +517,7 @@ "enable_friend_request_notifications": "Cuando recibís una solicitud de amistad", "enable_auto_install": "Descargar actualizaciones automáticamente", "common_redist": "Common redistributables", - "common_redist_description": "Common redistributables son requeridos para algunos juegos. Es recomendable instalarlos para evitar algunos problemas.", + "common_redist_description": "Los common redistributables son requeridos para algunos juegos. Es recomendable instalarlos para evitar algunos problemas.", "install_common_redist": "Instalar", "installing_common_redist": "Instalando…", "show_download_speed_in_megabytes": "Mostrar velocidad de descarga en megabytes por segundo", @@ -465,6 +539,8 @@ "hidden": "Oculto", "test_notification": "Probar notificación", "notification_preview": "Probar notificación de logro", + "debrid": "Debrid", + "debrid_description": "Los servicios Debrid son descargadores premium sin restricciones que te dejan descargar más rápido archivos alojados en servicios de alojamiento siendo que la única limitación es tu velocidad de internet.", "enable_friend_start_game_notifications": "Cuando un amigo está jugando un juego" }, "notifications": { @@ -492,6 +568,7 @@ "game_card": { "available_one": "Disponible", "available_other": "Disponibles", + "calculating": "Calculando", "no_downloads": "Sin descargas disponibles" }, "binary_not_found_modal": { @@ -593,6 +670,12 @@ "error_adding_friend": "No se pudo enviar la solicitud de amistad. Por favor revisá el código", "friend_code_length_error": "El código de amistad debe tener mínimo 8 caracteres", "game_removed_from_pinned": "Juego removido de fijados", + "amount_hours_short": "{{amount}}h", + "amount_minutes_short": "{{amount}}m", + "karma": "Karma", + "karma_count": "karma", + "karma_description": "Conseguido por me gustas positivos en reseñas", + "sort_by": "Filtrar por:", "game_added_to_pinned": "Juego añadido a fijados" }, "achievement": { diff --git a/src/main/services/hydra-api.ts b/src/main/services/hydra-api.ts index dd26e6f0..07f81d68 100644 --- a/src/main/services/hydra-api.ts +++ b/src/main/services/hydra-api.ts @@ -29,7 +29,7 @@ export class HydraApi { private static instance: AxiosInstance; private static readonly EXPIRATION_OFFSET_IN_MS = 1000 * 60 * 5; // 5 minutes - private static readonly ADD_LOG_INTERCEPTOR = true; + private static readonly ADD_LOG_INTERCEPTOR = false; private static secondsToMilliseconds(seconds: number) { return seconds * 1000; diff --git a/src/main/services/python-rpc.ts b/src/main/services/python-rpc.ts index f3ce9f6c..2a1dce79 100644 --- a/src/main/services/python-rpc.ts +++ b/src/main/services/python-rpc.ts @@ -106,7 +106,7 @@ export class PythonRPC { "main.py" ); - const childProcess = cp.spawn("python3", [scriptPath, ...commonArgs], { + const childProcess = cp.spawn("python", [scriptPath, ...commonArgs], { stdio: ["inherit", "inherit"], }); diff --git a/src/renderer/src/pages/game-details/description-header/description-header.scss b/src/renderer/src/pages/game-details/description-header/description-header.scss index a29caa34..74126fd5 100644 --- a/src/renderer/src/pages/game-details/description-header/description-header.scss +++ b/src/renderer/src/pages/game-details/description-header/description-header.scss @@ -11,7 +11,6 @@ border-radius: 8px; border: 1px solid rgba(255, 255, 255, 0.05); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); - margin-bottom: calc(globals.$spacing-unit * 1.5); &__info { display: flex; diff --git a/src/renderer/src/pages/game-details/gallery-slider/gallery-slider.scss b/src/renderer/src/pages/game-details/gallery-slider/gallery-slider.scss index 6f9e753c..f9da431d 100644 --- a/src/renderer/src/pages/game-details/gallery-slider/gallery-slider.scss +++ b/src/renderer/src/pages/game-details/gallery-slider/gallery-slider.scss @@ -2,7 +2,7 @@ .gallery-slider { &__container { - padding: calc(globals.$spacing-unit * 1.5) calc(globals.$spacing-unit * 1); + padding: calc(globals.$spacing-unit * 1.5) 0; width: 100%; display: flex; flex-direction: column; diff --git a/src/renderer/src/pages/game-details/game-details-content.tsx b/src/renderer/src/pages/game-details/game-details-content.tsx index e019d984..ab51a212 100644 --- a/src/renderer/src/pages/game-details/game-details-content.tsx +++ b/src/renderer/src/pages/game-details/game-details-content.tsx @@ -1,4 +1,4 @@ -import { useContext, useEffect, useMemo, useRef, useState } from "react"; +import { useContext, useEffect, useMemo, useState } from "react"; import { PencilIcon } from "@primer/octicons-react"; import { useTranslation } from "react-i18next"; @@ -17,6 +17,7 @@ import cloudIconAnimated from "@renderer/assets/icons/cloud-animated.gif"; import { useUserDetails, useLibrary } from "@renderer/hooks"; import { useSubscription } from "@renderer/hooks/use-subscription"; import "./game-details.scss"; +import "./hero.scss"; const processMediaElements = (document: Document) => { const $images = Array.from(document.querySelectorAll("img")); @@ -53,8 +54,6 @@ const getImageWithCustomPriority = ( }; export function GameDetailsContent() { - const heroRef = useRef(null); - const { t } = useTranslation("game_details"); const { @@ -152,19 +151,11 @@ export function GameDetailsContent() { className={`game-details__wrapper ${hasNSFWContentBlocked ? "game-details__wrapper--blurred" : ""}`} >
-
-
- {game?.title} -
-
+ {game?.title}
+ +
+ +
- -
diff --git a/src/renderer/src/pages/game-details/game-details-skeleton.tsx b/src/renderer/src/pages/game-details/game-details-skeleton.tsx index 750f92e1..7fc2a176 100644 --- a/src/renderer/src/pages/game-details/game-details-skeleton.tsx +++ b/src/renderer/src/pages/game-details/game-details-skeleton.tsx @@ -1,63 +1,170 @@ import Skeleton from "react-loading-skeleton"; -import { Button } from "@renderer/components"; -import { useTranslation } from "react-i18next"; -import "./game-details.scss"; +import "react-loading-skeleton/dist/skeleton.css"; export function GameDetailsSkeleton() { - const { t } = useTranslation("game_details"); - return ( -
-
- -
-
-
- - -
-
-
-
-
-
- - -
+
+
+
+ + +
+
+
+
+
+ +
+
+
+
+ + +
+
+ + + +
+
+
+
-
- {Array.from({ length: 3 }).map((_, index) => ( - - ))} - - {Array.from({ length: 2 }).map((_, index) => ( - - ))} - - +
+ +
+
+
+
+ + +
+
+ +
+ +
+ +
+ + +
+ + +
+ +
-
-
- - -
-
- {Array.from({ length: 6 }).map((_, index) => ( - - ))} -
-
-
+
); } diff --git a/src/renderer/src/pages/game-details/game-details.scss b/src/renderer/src/pages/game-details/game-details.scss index 14b583ee..f5f77a86 100644 --- a/src/renderer/src/pages/game-details/game-details.scss +++ b/src/renderer/src/pages/game-details/game-details.scss @@ -1,19 +1,5 @@ @use "../../scss/globals.scss"; -$hero-height: 300px; - -@keyframes slide-in { - 0% { - transform: translateY(calc(40px + globals.$spacing-unit * 2)); - opacity: 0; - } - - 100% { - transform: translateY(0); - opacity: 1; - } -} - .game-details { &__wrapper { display: flex; @@ -27,645 +13,6 @@ $hero-height: 300px; } } - &__review-form { - display: flex; - flex-direction: column; - gap: 16px; - margin-bottom: 24px; - } - - &__review-form-controls { - display: flex; - gap: calc(globals.$spacing-unit * 2); - align-items: flex-end; - flex-wrap: wrap; - - @media (max-width: 768px) { - flex-direction: column; - align-items: stretch; - gap: calc(globals.$spacing-unit * 1.5); - } - } - - &__review-form-bottom { - display: flex; - justify-content: space-between; - align-items: center; - gap: 16px; - flex-wrap: wrap; - } - - &__review-message { - padding: calc(globals.$spacing-unit * 1); - border-radius: 4px; - font-size: globals.$small-font-size; - font-weight: 500; - margin-top: calc(globals.$spacing-unit * 1); - border: 1px solid; - - &--success { - background: rgba(34, 197, 94, 0.1); - color: #86efac; - border-color: rgba(34, 197, 94, 0.3); - } - - &--error { - background: rgba(239, 68, 68, 0.1); - color: #fca5a5; - border-color: rgba(239, 68, 68, 0.3); - } - } - - &__review-score-container { - display: flex; - align-items: center; - gap: 4px; - } - - &__review-score-label { - font-size: 14px; - color: #ffffff; - font-weight: 500; - } - - &__review-score-select { - background-color: #2a2a2a; - border: 1px solid #3a3a3a; - border-radius: 4px; - color: #ffffff; - padding: 6px 12px; - font-size: 14px; - cursor: pointer; - transition: - border-color 0.2s ease, - background-color 0.2s ease; - - &:focus { - outline: none; - } - - &--red { - border-color: #e74c3c; - background-color: rgba(231, 76, 60, 0.1); - } - - &--yellow { - border-color: #f39c12; - background-color: rgba(243, 156, 18, 0.1); - } - - &--green { - border-color: #27ae60; - background-color: rgba(39, 174, 96, 0.1); - } - - option { - background-color: #2a2a2a; - color: #ffffff; - } - } - - &__star-rating { - display: flex; - align-items: center; - gap: 2px; - } - - &__star { - background: none; - border: none; - color: #666666; - cursor: pointer; - padding: 2px; - border-radius: 4px; - display: flex; - align-items: center; - justify-content: center; - transition: all 0.2s ease; - - &:hover { - color: #ffffff; - background-color: rgba(255, 255, 255, 0.1); - transform: scale(1.1); - } - - &--filled { - color: #ffffff; - - &.game-details__review-score-select--red { - color: #e74c3c; - } - - &.game-details__review-score-select--yellow { - color: #f39c12; - } - - &.game-details__review-score-select--green { - color: #27ae60; - } - } - - &--empty { - color: #666666; - - &:hover { - color: #ffffff; - } - } - - svg { - fill: currentColor; - } - } - - &__reviews-sort { - display: flex; - flex-direction: column; - gap: calc(globals.$spacing-unit * 0.75); - min-width: 150px; - } - - &__reviews-sort-label { - display: block; - font-size: globals.$body-font-size; - color: globals.$body-color; - } - - &__reviews-sort-select { - background-color: rgba(255, 255, 255, 0.05); - border: 1px solid globals.$border-color; - border-radius: 4px; - padding: calc(globals.$spacing-unit * 0.75) calc(globals.$spacing-unit * 1); - color: globals.$body-color; - font-size: globals.$body-font-size; - font-family: inherit; - cursor: pointer; - transition: - border-color 0.2s ease, - background-color 0.2s ease; - - &:focus { - outline: none; - background-color: rgba(255, 255, 255, 0.08); - border-color: globals.$brand-teal; - } - - &:hover { - border-color: rgba(255, 255, 255, 0.15); - } - - option { - background-color: globals.$dark-background-color; - color: globals.$body-color; - } - } - - &__reviews-list { - margin-top: calc(globals.$spacing-unit * 3); - } - - &__reviews-container { - display: flex; - flex-direction: column; - gap: calc(globals.$spacing-unit * 4); - } - - &__reviews-separator { - height: 1px; - background: rgba(255, 255, 255, 0.1); - margin: calc(globals.$spacing-unit * 3) 0; - width: 100%; - } - - &__reviews-list-header { - display: flex; - justify-content: space-between; - align-items: center; - padding-bottom: calc(globals.$spacing-unit * 1); - } - - &__reviews-empty { - text-align: center; - padding: calc(globals.$spacing-unit * 4) calc(globals.$spacing-unit * 2); - margin-bottom: calc(globals.$spacing-unit * 2); - } - - &__reviews-empty-icon { - font-size: 48px; - margin-bottom: calc(globals.$spacing-unit * 2); - color: rgba(255, 255, 255, 0.6); - } - - &__reviews-empty-title { - color: rgba(255, 255, 255, 0.9); - font-weight: 600; - margin: 0 0 calc(globals.$spacing-unit * 1) 0; - } - - &__reviews-empty-message { - color: rgba(255, 255, 255, 0.6); - font-size: globals.$small-font-size; - margin: 0; - line-height: 1.4; - } - - &__review-item { - overflow: hidden; - word-wrap: break-word; - } - - &__review-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: calc(globals.$spacing-unit * 1.5); - } - - &__review-user { - display: flex; - align-items: center; - gap: calc(globals.$spacing-unit * 1); - } - - &__review-user-info { - display: flex; - flex-direction: column; - gap: calc(globals.$spacing-unit * 0.25); - } - - &__review-display-name { - color: rgba(255, 255, 255, 0.9); - font-size: globals.$small-font-size; - font-weight: 600; - display: inline-flex; - - &--clickable { - cursor: pointer; - transition: color 0.2s ease; - - &:hover { - text-decoration: underline; - } - } - } - - &__review-actions { - margin-top: 12px; - padding-top: 8px; - border-top: 1px solid rgba(255, 255, 255, 0.1); - display: flex; - justify-content: space-between; - align-items: center; - } - - &__review-votes { - display: flex; - gap: 12px; - } - - &__vote-button { - display: flex; - align-items: center; - gap: 6px; - background: rgba(255, 255, 255, 0.05); - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: 6px; - padding: 6px 12px; - color: #ccc; - font-size: 14px; - cursor: pointer; - transition: all 0.2s ease; - - &:hover { - background: rgba(255, 255, 255, 0.1); - border-color: rgba(255, 255, 255, 0.2); - color: #ffffff; - } - - &--active { - &.game-details__vote-button--upvote { - svg { - fill: white; - } - } - - &.game-details__vote-button--downvote { - svg { - fill: white; - } - } - } - - span { - font-weight: 500; - display: inline-block; - min-width: 1ch; - overflow: hidden; - } - } - - &__delete-review-button { - display: flex; - align-items: center; - justify-content: center; - background: rgba(244, 67, 54, 0.1); - border: 1px solid rgba(244, 67, 54, 0.3); - border-radius: 6px; - padding: 6px; - color: #f44336; - cursor: pointer; - transition: all 0.2s ease; - gap: 6px; - - &:hover { - background: rgba(244, 67, 54, 0.2); - border-color: #f44336; - color: #ff5722; - } - } - - &__blocked-review-simple { - color: rgba(255, 255, 255, 0.6); - font-size: globals.$small-font-size; - display: flex; - align-items: center; - gap: calc(globals.$spacing-unit * 0.5); - } - - &__blocked-review-show-link { - background: none; - border: none; - color: #ffc107; - font-size: globals.$small-font-size; - cursor: pointer; - text-decoration: underline; - padding: 0; - transition: color 0.2s ease; - - &:hover { - color: #ffeb3b; - } - } - - &__blocked-review-hide-link { - background: none; - border: none; - color: rgba(255, 255, 255, 0.5); - font-size: globals.$small-font-size; - cursor: pointer; - text-decoration: underline; - padding: 0; - transition: color 0.2s ease; - - &:hover { - color: rgba(255, 255, 255, 0.8); - } - } - - &__review-score-stars { - display: flex; - align-items: center; - gap: 2px; - } - - &__review-star { - color: #666666; - transition: color 0.2s ease; - cursor: default; - - &--filled { - color: #ffffff; - - &.game-details__review-score--red { - color: #fca5a5; - } - - &.game-details__review-score--yellow { - color: #fcd34d; - } - - &.game-details__review-score--green { - color: #86efac; - } - } - - &--empty { - color: #666666; - } - - svg { - fill: currentColor; - } - } - - &__review-date { - display: flex; - align-items: center; - gap: 4px; - color: rgba(255, 255, 255, 0.6); - font-size: globals.$small-font-size; - } - - &__review-content { - color: globals.$body-color; - line-height: 1.5; - word-wrap: break-word; - word-break: break-word; - overflow-wrap: break-word; - white-space: pre-wrap; - max-width: 100%; - } - - &__reviews-loading { - text-align: center; - color: rgba(255, 255, 255, 0.6); - padding: calc(globals.$spacing-unit * 2); - } - - &__load-more-reviews { - background: rgba(255, 255, 255, 0.05); - border: 1px solid globals.$border-color; - color: globals.$body-color; - padding: calc(globals.$spacing-unit * 1) calc(globals.$spacing-unit * 2); - border-radius: 4px; - cursor: pointer; - font-size: globals.$body-font-size; - font-family: inherit; - transition: all 0.2s ease; - width: 100%; - margin-top: calc(globals.$spacing-unit * 2); - - &:hover { - background-color: rgba(255, 255, 255, 0.1); - border-color: globals.$brand-teal; - } - } - - &__hero { - width: 100%; - height: $hero-height; - min-height: $hero-height; - display: flex; - flex-direction: column; - position: relative; - transition: all ease 0.2s; - - @media (min-width: 1250px) { - height: 350px; - min-height: 350px; - } - } - - &__hero-content { - padding: calc(globals.$spacing-unit * 1.5); - height: 100%; - width: 100%; - display: flex; - justify-content: space-between; - align-items: flex-end; - - @media (min-width: 768px) { - padding: calc(globals.$spacing-unit * 2); - } - } - - &__hero-buttons { - display: flex; - gap: globals.$spacing-unit; - align-items: center; - - &--right { - margin-left: auto; - } - } - - &__edit-custom-game-button { - padding: calc(globals.$spacing-unit * 1.5); - background-color: rgba(0, 0, 0, 0.6); - backdrop-filter: blur(20px); - border-radius: 8px; - transition: all ease 0.2s; - cursor: pointer; - min-height: 40px; - min-width: 40px; - display: flex; - align-items: center; - justify-content: center; - color: globals.$muted-color; - border: solid 1px globals.$border-color; - box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.8); - animation: slide-in 0.3s cubic-bezier(0.33, 1, 0.68, 1); - - &:active { - opacity: 0.9; - } - - &:hover { - background-color: rgba(0, 0, 0, 0.5); - color: globals.$body-color; - } - } - - &__hero-logo-backdrop { - width: 100%; - height: 100%; - position: absolute; - display: flex; - flex-direction: column; - justify-content: space-between; - } - &__hero-image-wrapper { - position: absolute; - width: 100%; - height: 384px; - max-height: 384px; - overflow: hidden; - border-radius: 0px 0px 8px 8px; - z-index: 0; - - &::after { - content: ""; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: linear-gradient( - 0deg, - rgba(0, 0, 0, 0.3) 60%, - transparent 100% - ); - z-index: 1; - pointer-events: none; - border-radius: inherit; - } - - @media (min-width: 1250px) { - height: calc(350px + 82px); - min-height: calc(350px + 84px); - } - } - - &__hero-image { - width: 100%; - height: 100%; - object-fit: cover; - object-position: top; - transition: all ease 0.2s; - position: absolute; - z-index: 0; - border-radius: 0px 0px 8px 8px; - - @media (min-width: 1250px) { - object-position: center; - } - } - - &__game-logo { - width: 200px; - align-self: flex-end; - - @media (min-width: 768px) { - width: 250px; - } - - @media (min-width: 1024px) { - width: 300px; - } - } - - &__game-logo-text { - width: 200px; - align-self: flex-end; - font-size: 1.8rem; - font-weight: bold; - color: #ffffff; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8); - text-align: left; - line-height: 1.2; - word-wrap: break-word; - overflow-wrap: break-word; - hyphens: auto; - - @media (min-width: 768px) { - width: 250px; - font-size: 2.2rem; - } - - @media (min-width: 1024px) { - width: 300px; - font-size: 2.5rem; - } - } - - &__hero-image-skeleton { - height: 300px; - - @media (min-width: 1250px) { - height: 350px; - } - } - &__container { width: 100%; height: 100%; @@ -674,6 +21,7 @@ $hero-height: 300px; z-index: 1; } + // Description Section Styles &__description-container { display: flex; width: 100%; @@ -782,322 +130,51 @@ $hero-height: 300px; } } - &__description-skeleton { - display: flex; - flex-direction: column; - gap: globals.$spacing-unit; - padding: calc(globals.$spacing-unit * 2) calc(globals.$spacing-unit * 1.5); - width: 100%; - margin-left: auto; - margin-right: auto; - - @media (min-width: 768px) { - padding: calc(globals.$spacing-unit * 2.5) calc(globals.$spacing-unit * 2); + // Skeleton-specific styles + &__skeleton { + .react-loading-skeleton { + background: linear-gradient(90deg, #1c1c1c 25%, #2a2a2a 50%, #1c1c1c 75%); + background-size: 200% 100%; + animation: skeleton-loading 1.5s infinite; } - @media (min-width: 1024px) { - padding: calc(globals.$spacing-unit * 3) calc(globals.$spacing-unit * 2); - width: 80%; + // Ensure skeleton elements maintain proper spacing + .description-header { + margin-bottom: calc(globals.$spacing-unit * 1.5); } - @media (min-width: 1280px) { - width: 60%; - line-height: 22px; + .content-sidebar { + min-width: 300px; + max-width: 300px; } - @media (min-width: 1536px) { - width: 50%; - } - } - - &__randomizer-button { - animation: slide-in 0.2s; - position: fixed; - bottom: calc(globals.$spacing-unit * 3); - right: calc(9px + globals.$spacing-unit * 2); - box-shadow: rgba(255, 255, 255, 0.1) 0px 0px 10px 1px; - border: solid 2px globals.$border-color; - z-index: 1; - background-color: globals.$background-color; - - &:hover { - background-color: globals.$background-color; - box-shadow: rgba(255, 255, 255, 0.1) 0px 0px 15px 5px; - opacity: 1; - } - - &:active { - transform: scale(0.98); - } - - &:disabled { - box-shadow: none; - transform: none; - opacity: 0.8; - background-color: globals.$background-color; - } - } - - &__hero-panel-skeleton { - width: 100%; - padding: calc(globals.$spacing-unit * 2); - display: flex; - align-items: center; - background-color: globals.$background-color; - height: 72px; - border-bottom: solid 1px globals.$border-color; - } - - &__cloud-sync-button { - padding: calc(globals.$spacing-unit * 1.5) calc(globals.$spacing-unit * 2); - background-color: rgba(0, 0, 0, 0.6); - backdrop-filter: blur(20px); - border-radius: 8px; - transition: all ease 0.2s; - cursor: pointer; - min-height: 40px; - display: flex; - align-items: center; - justify-content: center; - gap: globals.$spacing-unit; - color: globals.$muted-color; - font-size: globals.$small-font-size; - border: solid 1px globals.$border-color; - box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.8); - animation: slide-in 0.3s cubic-bezier(0.33, 1, 0.68, 1); - - &:active { - opacity: 0.9; - } - - &:disabled { - opacity: globals.$disabled-opacity; - cursor: not-allowed; - } - - &:hover { - background-color: rgba(0, 0, 0, 0.5); - } - } - - &__stars-icon-container { - width: 16px; - height: 16px; - position: relative; - } - - &__stars-icon { - width: 70px; - position: absolute; - top: -28px; - left: -27px; - } - - &__cloud-icon-container { - width: 20px; - height: 16px; - display: flex; - align-items: center; - justify-content: center; - position: relative; - } - - &__cloud-icon { - width: 26px; - position: absolute; - top: -3px; - } - - &__hero-backdrop { - flex: 1; - transition: opacity 0.2s ease; - } - - &__reviews-section { - margin-top: calc(globals.$spacing-unit * 3); - padding-top: calc(globals.$spacing-unit * 3); - border-top: 1px solid rgba(255, 255, 255, 0.1); - width: 100%; - margin-left: auto; - margin-right: auto; - - @media (min-width: 1280px) { - width: 60%; - } - - @media (min-width: 1536px) { - width: 50%; - } - } - - &__reviews-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: calc(globals.$spacing-unit * 2); - - @media (max-width: 768px) { + // Hero panel skeleton spacing + .hero-panel__content { + display: flex; flex-direction: column; - align-items: flex-start; - gap: calc(globals.$spacing-unit * 1.5); - } - } - - &__reviews-title { - font-size: 1.25rem; - font-weight: 600; - color: globals.$muted-color; - margin: 0; - } - - &__reviews-title-group { - display: flex; - align-items: center; - gap: calc(globals.$spacing-unit); - flex: 1; - } - - &__reviews-badge { - background-color: rgba(255, 255, 255, 0.1); - color: rgba(255, 255, 255, 0.7); - padding: 4px 8px; - border-radius: 6px; - font-size: 12px; - font-weight: 600; - min-width: 24px; - text-align: center; - flex-shrink: 0; - } - - &__leave-review-cta { - display: flex; - align-items: center; - gap: calc(globals.$spacing-unit * 0.5); - padding: calc(globals.$spacing-unit * 0.75) - calc(globals.$spacing-unit * 1.5); - background: linear-gradient( - 135deg, - globals.$brand-teal, - globals.$brand-blue - ); - color: white; - border: none; - border-radius: 8px; - font-size: 0.9rem; - font-weight: 600; - cursor: pointer; - transition: all 0.2s ease; - margin-bottom: calc(globals.$spacing-unit); - - &:hover { - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(globals.$brand-teal, 0.3); + gap: calc(globals.$spacing-unit * 0.5); } - &:active { - transform: translateY(0); + // Review items skeleton spacing + .review-item-skeleton { + border: 1px solid globals.$border-color; + border-radius: 8px; + padding: calc(globals.$spacing-unit * 1); + margin-bottom: calc(globals.$spacing-unit * 1); } - svg { - flex-shrink: 0; - } - } - - &__review-input-container { - display: flex; - flex-direction: column; - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: 8px; - background-color: globals.$dark-background-color; - overflow: hidden; - } - - &__review-input-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 8px 12px; - background-color: globals.$background-color; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); - } - - &__review-editor-toolbar { - display: flex; - gap: 4px; - } - - &__editor-button { - background: none; - border: 1px solid rgba(255, 255, 255, 0.15); - border-radius: 4px; - color: #ffffff; - padding: 4px 8px; - cursor: pointer; - font-size: 12px; - transition: all 0.2s ease; - - &:hover { - background-color: rgba(255, 255, 255, 0.08); - border-color: rgba(255, 255, 255, 0.2); - } - - &.is-active { - background-color: globals.$brand-blue; - border-color: globals.$brand-blue; - } - - &:disabled { - opacity: 0.5; - cursor: not-allowed; - } - } - - &__review-char-counter { - font-size: 12px; - color: #888888; - - .over-limit { - color: #ff6b6b; - } - } - - &__review-input { - min-height: 120px; - padding: 12px; - cursor: text; - - .ProseMirror { - outline: none; - color: #ffffff; - font-size: 14px; - line-height: 1.5; - min-height: 96px; // 120px - 24px padding - width: 100%; - cursor: text; - - &:focus { - outline: none; - } - - p { - margin: 0 0 8px 0; - - &:last-child { - margin-bottom: 0; - } - } - - strong { - font-weight: bold; - } - - em { - font-style: italic; - } - - u { - text-decoration: underline; - } + // Sidebar section spacing + .sidebar-section-skeleton { + margin-bottom: calc(globals.$spacing-unit * 1.5); } } } + +@keyframes skeleton-loading { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} diff --git a/src/renderer/src/pages/game-details/game-details.tsx b/src/renderer/src/pages/game-details/game-details.tsx index f0778494..c1b8b551 100644 --- a/src/renderer/src/pages/game-details/game-details.tsx +++ b/src/renderer/src/pages/game-details/game-details.tsx @@ -25,6 +25,7 @@ import { Downloader, getDownloadersForUri } from "@shared"; import { CloudSyncModal } from "./cloud-sync-modal/cloud-sync-modal"; import { CloudSyncFilesModal } from "./cloud-sync-files-modal/cloud-sync-files-modal"; import "./game-details.scss"; +import "./hero.scss"; export default function GameDetails() { const [randomGame, setRandomGame] = useState(null); diff --git a/src/renderer/src/pages/game-details/game-reviews.scss b/src/renderer/src/pages/game-details/game-reviews.scss new file mode 100644 index 00000000..e3a187b6 --- /dev/null +++ b/src/renderer/src/pages/game-details/game-reviews.scss @@ -0,0 +1,116 @@ +@use "../../scss/globals.scss"; + +.game-details { + &__reviews-section { + margin-top: calc(globals.$spacing-unit * 3); + padding-top: calc(globals.$spacing-unit * 3); + border-top: 1px solid rgba(255, 255, 255, 0.1); + width: 100%; + margin-left: auto; + margin-right: auto; + + @media (min-width: 1280px) { + width: 60%; + } + + @media (min-width: 1536px) { + width: 50%; + } + } + + &__reviews-title { + font-size: 1.25rem; + font-weight: 600; + color: globals.$muted-color; + margin: 0; + } + + &__reviews-title-group { + display: flex; + align-items: center; + gap: calc(globals.$spacing-unit); + flex: 1; + } + + &__reviews-badge { + background-color: rgba(255, 255, 255, 0.1); + color: rgba(255, 255, 255, 0.7); + padding: 4px 8px; + border-radius: 6px; + font-size: 12px; + font-weight: 600; + min-width: 24px; + text-align: center; + flex-shrink: 0; + } + + &__reviews-container { + display: flex; + flex-direction: column; + gap: calc(globals.$spacing-unit * 4); + } + + &__reviews-separator { + height: 1px; + background: rgba(255, 255, 255, 0.1); + margin: calc(globals.$spacing-unit * 3) 0; + width: 100%; + } + + &__reviews-list-header { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: calc(globals.$spacing-unit * 1); + } + + &__reviews-empty { + text-align: center; + padding: calc(globals.$spacing-unit * 4) calc(globals.$spacing-unit * 2); + margin-bottom: calc(globals.$spacing-unit * 2); + } + + &__reviews-empty-icon { + font-size: 48px; + margin-bottom: calc(globals.$spacing-unit * 2); + color: rgba(255, 255, 255, 0.6); + } + + &__reviews-empty-title { + color: rgba(255, 255, 255, 0.9); + font-weight: 600; + margin: 0 0 calc(globals.$spacing-unit * 1) 0; + } + + &__reviews-empty-message { + color: rgba(255, 255, 255, 0.6); + font-size: globals.$small-font-size; + margin: 0; + line-height: 1.4; + } + + &__reviews-loading { + text-align: center; + color: rgba(255, 255, 255, 0.6); + padding: calc(globals.$spacing-unit * 2); + } + + &__load-more-reviews { + background: rgba(255, 255, 255, 0.05); + border: 1px solid globals.$border-color; + color: globals.$body-color; + padding: calc(globals.$spacing-unit * 1) calc(globals.$spacing-unit * 2); + border-radius: 4px; + cursor: pointer; + font-size: globals.$body-font-size; + font-family: inherit; + transition: all 0.2s ease; + width: 100%; + margin-top: calc(globals.$spacing-unit * 2); + + &:hover { + background-color: rgba(255, 255, 255, 0.1); + border-color: globals.$brand-teal; + } + } +} diff --git a/src/renderer/src/pages/game-details/game-reviews.tsx b/src/renderer/src/pages/game-details/game-reviews.tsx index 1ce44550..f70c84b2 100644 --- a/src/renderer/src/pages/game-details/game-reviews.tsx +++ b/src/renderer/src/pages/game-details/game-reviews.tsx @@ -9,6 +9,7 @@ import { ReviewForm } from "./review-form"; import { ReviewItem } from "./review-item"; import { ReviewSortOptions } from "./review-sort-options"; import { ReviewPromptBanner } from "./review-prompt-banner"; +import "./game-reviews.scss"; import { useToast } from "@renderer/hooks"; type ReviewSortOption = @@ -465,84 +466,82 @@ export function GameReviews({ )} -
-
-
-

{t("reviews")}

- - {totalReviewCount} - -
+
+
+

{t("reviews")}

+ + {totalReviewCount} +
- - - {reviewsLoading && reviews.length === 0 && ( -
- {t("loading_reviews")} -
- )} - - {!reviewsLoading && reviews.length === 0 && ( -
-
- -
-

- {t("no_reviews_yet")} -

-

- {t("be_first_to_review")} -

-
- )} - -
0 ? 0.5 : 1, - transition: "opacity 0.2s ease", - }} - > - {reviews.map((review) => ( - - ))} -
- - {hasMoreReviews && !reviewsLoading && ( - - )} - - {reviewsLoading && reviews.length > 0 && ( -
- {t("loading_more_reviews")} -
- )}
+ + + {reviewsLoading && reviews.length === 0 && ( +
+ {t("loading_reviews")} +
+ )} + + {!reviewsLoading && reviews.length === 0 && ( +
+
+ +
+

+ {t("no_reviews_yet")} +

+

+ {t("be_first_to_review")} +

+
+ )} + +
0 ? 0.5 : 1, + transition: "opacity 0.2s ease", + }} + > + {reviews.map((review) => ( + + ))} +
+ + {hasMoreReviews && !reviewsLoading && ( + + )} + + {reviewsLoading && reviews.length > 0 && ( +
+ {t("loading_more_reviews")} +
+ )}
); } diff --git a/src/renderer/src/pages/game-details/hero.scss b/src/renderer/src/pages/game-details/hero.scss new file mode 100644 index 00000000..6bd63320 --- /dev/null +++ b/src/renderer/src/pages/game-details/hero.scss @@ -0,0 +1,271 @@ +@use "../../scss/globals.scss"; + +$hero-height: 350px; + +@keyframes slide-in { + 0% { + transform: translateY(calc(40px + globals.$spacing-unit * 2)); + opacity: 0; + } + + 100% { + transform: translateY(0); + opacity: 1; + } +} + +.game-details { + &__hero-panel { + padding: globals.$spacing-unit; + } + + &__hero { + width: 100%; + height: $hero-height; + min-height: $hero-height; + display: flex; + flex-direction: column; + position: relative; + transition: all ease 0.2s; + + @media (min-width: 1250px) { + height: 350px; + min-height: 350px; + } + } + + &__hero-content { + padding: calc(globals.$spacing-unit * 1.5); + height: 100%; + width: 100%; + display: flex; + justify-content: space-between; + align-items: flex-end; + + @media (min-width: 768px) { + padding: calc(globals.$spacing-unit * 2); + } + } + + &__hero-buttons { + display: flex; + gap: globals.$spacing-unit; + align-items: center; + + &--right { + margin-left: auto; + } + } + + &__edit-custom-game-button { + padding: calc(globals.$spacing-unit * 1.5); + background-color: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(20px); + border-radius: 8px; + transition: all ease 0.2s; + cursor: pointer; + min-height: 40px; + min-width: 40px; + display: flex; + align-items: center; + justify-content: center; + color: globals.$muted-color; + border: solid 1px globals.$border-color; + box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.8); + animation: slide-in 0.3s cubic-bezier(0.33, 1, 0.68, 1); + + &:active { + opacity: 0.9; + } + + &:hover { + background-color: rgba(0, 0, 0, 0.5); + color: globals.$body-color; + } + } + + &__hero-logo-backdrop { + width: 100%; + height: 100%; + position: absolute; + display: flex; + flex-direction: column; + justify-content: space-between; + } + + &__hero-image-wrapper { + position: absolute; + width: 100%; + height: 384px; + max-height: 384px; + overflow: hidden; + border-radius: 0px 0px 8px 8px; + z-index: 0; + + &::after { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient( + 0deg, + rgba(0, 0, 0, 0.3) 60%, + transparent 100% + ); + z-index: 1; + pointer-events: none; + border-radius: inherit; + } + + @media (min-width: 1250px) { + height: calc(350px + 82px); + min-height: calc(350px + 84px); + } + } + + &__hero-image { + width: 100%; + height: $hero-height; + min-height: $hero-height; + object-fit: cover; + object-position: top; + transition: all ease 0.2s; + position: absolute; + z-index: 0; + border-radius: 0px 0px 8px 8px; + + @media (min-width: 1250px) { + object-position: center; + height: $hero-height; + min-height: $hero-height; + } + } + + &__game-logo { + width: 200px; + align-self: flex-end; + + @media (min-width: 768px) { + width: 250px; + } + + @media (min-width: 1024px) { + width: 300px; + } + } + + &__game-logo-text { + width: 200px; + align-self: flex-end; + font-size: 1.8rem; + font-weight: bold; + color: #ffffff; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8); + text-align: left; + line-height: 1.2; + word-wrap: break-word; + overflow-wrap: break-word; + hyphens: auto; + + @media (min-width: 768px) { + width: 250px; + font-size: 2.2rem; + } + + @media (min-width: 1024px) { + width: 300px; + font-size: 2.5rem; + } + } + + &__cloud-sync-button { + padding: calc(globals.$spacing-unit * 1.5) calc(globals.$spacing-unit * 2); + background-color: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(20px); + border-radius: 8px; + transition: all ease 0.2s; + cursor: pointer; + min-height: 40px; + display: flex; + align-items: center; + justify-content: center; + gap: globals.$spacing-unit; + color: globals.$muted-color; + font-size: globals.$small-font-size; + border: solid 1px globals.$border-color; + box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.8); + animation: slide-in 0.3s cubic-bezier(0.33, 1, 0.68, 1); + + &:active { + opacity: 0.9; + } + + &:disabled { + opacity: globals.$disabled-opacity; + cursor: not-allowed; + } + + &:hover { + background-color: rgba(0, 0, 0, 0.5); + } + } + + &__cloud-icon-container { + width: 20px; + height: 16px; + display: flex; + align-items: center; + justify-content: center; + position: relative; + } + + &__cloud-icon { + width: 26px; + position: absolute; + top: -3px; + } + + &__randomizer-button { + padding: calc(globals.$spacing-unit * 1.5); + background-color: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(20px); + border-radius: 8px; + transition: all ease 0.2s; + cursor: pointer; + min-height: 40px; + min-width: 40px; + display: flex; + align-items: center; + justify-content: center; + color: globals.$muted-color; + border: solid 1px globals.$border-color; + box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.8); + animation: slide-in 0.3s cubic-bezier(0.33, 1, 0.68, 1); + + &:active { + opacity: 0.9; + } + + &:hover { + background-color: rgba(0, 0, 0, 0.5); + color: globals.$body-color; + } + } + + &__stars-icon-container { + width: 20px; + height: 16px; + display: flex; + align-items: center; + justify-content: center; + position: relative; + } + + &__stars-icon { + width: 26px; + position: absolute; + top: -3px; + } +} diff --git a/src/renderer/src/pages/game-details/hero/hero-panel.scss b/src/renderer/src/pages/game-details/hero/hero-panel.scss index a0d32e9e..c91e685c 100644 --- a/src/renderer/src/pages/game-details/hero/hero-panel.scss +++ b/src/renderer/src/pages/game-details/hero/hero-panel.scss @@ -20,11 +20,6 @@ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); border-radius: 8px; - &__container { - padding: 0px 12px 12px; - margin: 0; - } - &--stuck { background: rgba(0, 0, 0, 0.7); backdrop-filter: blur(12px); @@ -35,7 +30,18 @@ &__content { display: flex; flex-direction: column; - gap: globals.$spacing-unit; + gap: calc(globals.$spacing-unit * 0.5); + + p { + font-size: globals.$small-font-size; + color: globals.$muted-color; + font-weight: 400; + margin: 0; + + &:first-child { + font-weight: 600; + } + } } &__actions { diff --git a/src/renderer/src/pages/game-details/review-form.scss b/src/renderer/src/pages/game-details/review-form.scss new file mode 100644 index 00000000..7ec1d922 --- /dev/null +++ b/src/renderer/src/pages/game-details/review-form.scss @@ -0,0 +1,232 @@ +@use "../../scss/globals.scss"; + +.game-details { + &__reviews-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: calc(globals.$spacing-unit * 2); + + @media (max-width: 768px) { + flex-direction: column; + align-items: flex-start; + gap: calc(globals.$spacing-unit * 1.5); + } + } + + &__reviews-title { + font-size: 1.25rem; + font-weight: 600; + color: globals.$muted-color; + margin: 0; + } + + &__review-form { + display: flex; + flex-direction: column; + gap: 16px; + margin-bottom: 24px; + } + + &__review-form-bottom { + display: flex; + justify-content: space-between; + align-items: center; + gap: 16px; + flex-wrap: wrap; + } + + &__review-score-container { + display: flex; + align-items: center; + gap: 4px; + } + + &__review-score-select { + background-color: #2a2a2a; + border: 1px solid #3a3a3a; + border-radius: 4px; + color: #ffffff; + padding: 6px 12px; + font-size: 14px; + cursor: pointer; + transition: + border-color 0.2s ease, + background-color 0.2s ease; + + &:focus { + outline: none; + } + + &--red { + border-color: #e74c3c; + background-color: rgba(231, 76, 60, 0.1); + } + + &--yellow { + border-color: #f39c12; + background-color: rgba(243, 156, 18, 0.1); + } + + &--green { + border-color: #27ae60; + background-color: rgba(39, 174, 96, 0.1); + } + + option { + background-color: #2a2a2a; + color: #ffffff; + } + } + + &__star-rating { + display: flex; + align-items: center; + gap: 2px; + } + + &__star { + background: none; + border: none; + color: #666666; + cursor: pointer; + padding: 2px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + + &:hover { + color: #ffffff; + background-color: rgba(255, 255, 255, 0.1); + transform: scale(1.1); + } + + &--filled { + color: #ffffff; + + &.game-details__review-score-select--red { + color: #e74c3c; + } + + &.game-details__review-score-select--yellow { + color: #f39c12; + } + + &.game-details__review-score-select--green { + color: #27ae60; + } + } + + &--empty { + color: #666666; + + &:hover { + color: #ffffff; + } + } + + svg { + fill: currentColor; + } + } + + &__review-input-container { + display: flex; + flex-direction: column; + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 8px; + background-color: globals.$dark-background-color; + overflow: hidden; + } + + &__review-input-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 12px; + background-color: globals.$background-color; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + } + + &__review-editor-toolbar { + display: flex; + gap: 4px; + } + + &__editor-button { + background: none; + border: 1px solid rgba(255, 255, 255, 0.15); + border-radius: 4px; + color: #ffffff; + padding: 4px 8px; + cursor: pointer; + font-size: 12px; + transition: all 0.2s ease; + + &:hover { + background-color: rgba(255, 255, 255, 0.08); + border-color: rgba(255, 255, 255, 0.2); + } + + &.is-active { + background-color: globals.$brand-blue; + border-color: globals.$brand-blue; + } + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } + } + + &__review-char-counter { + font-size: 12px; + color: #888888; + + .over-limit { + color: #ff6b6b; + } + } + + &__review-input { + min-height: 120px; + padding: 12px; + cursor: text; + + .ProseMirror { + outline: none; + color: #ffffff; + font-size: 14px; + line-height: 1.5; + min-height: 96px; // 120px - 24px padding + width: 100%; + cursor: text; + + &:focus { + outline: none; + } + + p { + margin: 0 0 8px 0; + + &:last-child { + margin-bottom: 0; + } + } + + strong { + font-weight: bold; + } + + em { + font-style: italic; + } + + u { + text-decoration: underline; + } + } + } +} diff --git a/src/renderer/src/pages/game-details/review-form.tsx b/src/renderer/src/pages/game-details/review-form.tsx index 2cc83a19..ffcad4e3 100644 --- a/src/renderer/src/pages/game-details/review-form.tsx +++ b/src/renderer/src/pages/game-details/review-form.tsx @@ -2,6 +2,7 @@ import { Star } from "lucide-react"; import { useTranslation } from "react-i18next"; import { EditorContent, Editor } from "@tiptap/react"; import { Button } from "@renderer/components"; +import "./review-form.scss"; interface ReviewFormProps { editor: Editor | null; diff --git a/src/renderer/src/pages/game-details/review-item.scss b/src/renderer/src/pages/game-details/review-item.scss index e1651ef5..d4f2d38c 100644 --- a/src/renderer/src/pages/game-details/review-item.scss +++ b/src/renderer/src/pages/game-details/review-item.scss @@ -1,6 +1,213 @@ @use "../../scss/globals.scss"; .game-details { + &__review-item { + overflow: hidden; + word-wrap: break-word; + } + + &__review-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: calc(globals.$spacing-unit * 1.5); + } + + &__review-user { + display: flex; + align-items: center; + gap: calc(globals.$spacing-unit * 1); + } + + &__review-user-info { + display: flex; + flex-direction: column; + gap: calc(globals.$spacing-unit * 0.25); + } + + &__review-display-name { + color: rgba(255, 255, 255, 0.9); + font-size: globals.$small-font-size; + font-weight: 600; + display: inline-flex; + + &--clickable { + cursor: pointer; + transition: color 0.2s ease; + + &:hover { + text-decoration: underline; + } + } + } + + &__review-actions { + margin-top: 12px; + padding-top: 8px; + border-top: 1px solid rgba(255, 255, 255, 0.1); + display: flex; + justify-content: space-between; + align-items: center; + } + + &__review-votes { + display: flex; + gap: 12px; + } + + &__vote-button { + display: flex; + align-items: center; + gap: 6px; + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 6px; + padding: 6px 12px; + color: #ccc; + font-size: 14px; + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + background: rgba(255, 255, 255, 0.1); + border-color: rgba(255, 255, 255, 0.2); + color: #ffffff; + } + + &--active { + &.game-details__vote-button--upvote { + svg { + fill: white; + } + } + + &.game-details__vote-button--downvote { + svg { + fill: white; + } + } + } + + span { + font-weight: 500; + display: inline-block; + min-width: 1ch; + overflow: hidden; + } + } + + &__delete-review-button { + display: flex; + align-items: center; + justify-content: center; + background: rgba(244, 67, 54, 0.1); + border: 1px solid rgba(244, 67, 54, 0.3); + border-radius: 6px; + padding: 6px; + color: #f44336; + cursor: pointer; + transition: all 0.2s ease; + gap: 6px; + + &:hover { + background: rgba(244, 67, 54, 0.2); + border-color: #f44336; + color: #ff5722; + } + } + + &__blocked-review-simple { + color: rgba(255, 255, 255, 0.6); + font-size: globals.$small-font-size; + display: flex; + align-items: center; + gap: calc(globals.$spacing-unit * 0.5); + } + + &__blocked-review-show-link { + background: none; + border: none; + color: #ffc107; + font-size: globals.$small-font-size; + cursor: pointer; + text-decoration: underline; + padding: 0; + transition: color 0.2s ease; + + &:hover { + color: #ffeb3b; + } + } + + &__blocked-review-hide-link { + background: none; + border: none; + color: rgba(255, 255, 255, 0.5); + font-size: globals.$small-font-size; + cursor: pointer; + text-decoration: underline; + padding: 0; + transition: color 0.2s ease; + + &:hover { + color: rgba(255, 255, 255, 0.8); + } + } + + &__review-score-stars { + display: flex; + align-items: center; + gap: 2px; + } + + &__review-star { + color: #666666; + transition: color 0.2s ease; + cursor: default; + + &--filled { + color: #ffffff; + + &.game-details__review-score--red { + color: #fca5a5; + } + + &.game-details__review-score--yellow { + color: #fcd34d; + } + + &.game-details__review-score--green { + color: #86efac; + } + } + + &--empty { + color: #666666; + } + + svg { + fill: currentColor; + } + } + + &__review-date { + display: flex; + align-items: center; + gap: 4px; + color: rgba(255, 255, 255, 0.6); + font-size: globals.$small-font-size; + } + + &__review-content { + color: globals.$body-color; + line-height: 1.5; + word-wrap: break-word; + word-break: break-word; + overflow-wrap: break-word; + white-space: pre-wrap; + max-width: 100%; + } + &__review-translation-toggle { display: inline-flex; align-items: center;