diff --git a/client/src/views/GameInterface/tabs/DatapackTab.jsx b/client/src/views/GameInterface/tabs/DatapackTab.jsx index 6dda336..ee0aa5f 100644 --- a/client/src/views/GameInterface/tabs/DatapackTab.jsx +++ b/client/src/views/GameInterface/tabs/DatapackTab.jsx @@ -58,90 +58,92 @@ const DatapackTab = () => { return (
-
-
- {sections.map((s) => ( - - ))} + +
+
+ {sections.map((s) => ( + + ))} +
+ +
+ + setSearchQuery(e.target.value)} + /> +
-
- - setSearchQuery(e.target.value)} - /> -
-
- - -
- {displayList.map((item) => ( -
- setSelectedItem({ ...item, sectionType: activeSection }) - } - > -
- {item.texture ? ( - - ) : ( -
- {item.displayName?.[0] || "?"} -
- )} -
- -
- {item.displayName} - {item.id} - - {/* Секція луту без картинок, лише текст або іконка коробки */} - {activeSection === "hostiles" && - item.loot && - item.loot.length > 0 && ( -
- {item.loot.map((lootEntry, idx) => { - const lootData = GameDataManager.getItem(lootEntry.id); - return ( -
- - - {lootData?.displayName || - lootEntry.id.split(":").pop()} - -
- ); - })} +
+
+ {displayList.map((item) => ( +
+ setSelectedItem({ ...item, sectionType: activeSection }) + } + > +
+ {item.texture ? ( + + ) : ( +
+ {item.displayName?.[0] || "?"}
)} +
+ +
+ {item.displayName} + {item.id} + + {activeSection === "hostiles" && + item.loot && + item.loot.length > 0 && ( +
+ {item.loot.map((lootEntry, idx) => { + const lootData = GameDataManager.getItem( + lootEntry.id, + ); + return ( +
+ + + {lootData?.displayName || + lootEntry.id.split(":").pop()} + +
+ ); + })} +
+ )} +
-
- ))} + ))} +
- {selectedItem && ( { if (!recipe) return null; + const CONNECT_URL = getServerUrl(); + const ASSET_BASE_URL = `${CONNECT_URL}/static/`; + + const getFullTextureUrl = (path) => { + if (!path) return "/assets/no-image.png"; + if (path.startsWith("http")) return path; + return `${ASSET_BASE_URL}${path}`; + }; + const isBusy = !!activeCraft; const outputQty = Object.values(recipe.output || {})[0] || 1; const canAfford = recipe.ingredients?.every( @@ -19,7 +29,7 @@ const CraftModal = ({ return (
e.stopPropagation()}> -
+

Construction: {recipe.displayName}

@@ -29,6 +39,25 @@ const CraftModal = ({
+ {/* Секція з картинкою предмета */} +
+
+ {recipe.displayName} +
x{outputQty}
+
+
+ PROTOTYPE_UNIT +

+ {recipe.description || + "Technical data encrypted or unavailable."} +

+
+
+

Required Resources diff --git a/client/src/views/GameInterface/tabs/components/DatapackDetailsModal.css b/client/src/views/GameInterface/tabs/components/DatapackDetailsModal.css index 4d37798..3259bc6 100644 --- a/client/src/views/GameInterface/tabs/components/DatapackDetailsModal.css +++ b/client/src/views/GameInterface/tabs/components/DatapackDetailsModal.css @@ -10,10 +10,11 @@ animation: modalSlideUp 0.3s ease-out; } -.modal-header { +.modal-headerr { display: flex; align-items: center; gap: 20px; + justify-content: left; margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid rgba(255, 255, 255, 0.05); diff --git a/client/src/views/GameInterface/tabs/components/DatapackDetailsModal.jsx b/client/src/views/GameInterface/tabs/components/DatapackDetailsModal.jsx index 0689543..182341e 100644 --- a/client/src/views/GameInterface/tabs/components/DatapackDetailsModal.jsx +++ b/client/src/views/GameInterface/tabs/components/DatapackDetailsModal.jsx @@ -75,7 +75,7 @@ const DatapackDetailsModal = ({ data, onClose }) => { × -
+
{data.texture ? ( diff --git a/client/src/views/GameInterface/tabs/components/ItemModal.css b/client/src/views/GameInterface/tabs/components/ItemModal.css index 39290a0..26fa6c0 100644 --- a/client/src/views/GameInterface/tabs/components/ItemModal.css +++ b/client/src/views/GameInterface/tabs/components/ItemModal.css @@ -12,133 +12,184 @@ backdrop-filter: blur(4px); } -.modal-content { - background: #12151a; - border: 1px solid #00d2ff; - border-radius: 8px; - width: 100%; - max-width: 400px; - padding: 25px; +.datapack-modal-content { + background: #0f1115; + border: 1px solid rgba(0, 210, 255, 0.3); + width: 90%; + max-width: 450px; + border-radius: 12px; position: relative; - box-shadow: 0 0 30px rgba(0, 210, 255, 0.2); - color: #fff; - font-family: "Segoe UI", Roboto, Helvetica, Arial, sans-serif; -} - -.modal-close { - position: absolute; - top: 10px; - right: 15px; - background: none; - border: none; - color: #888; - font-size: 28px; - cursor: pointer; - transition: color 0.2s; -} - -.modal-close:hover { + padding: 25px; + box-shadow: 0 20px 50px rgba(0, 0, 0, 0.8); + animation: modalSlideUp 0.3s ease-out; color: #fff; } -.details-header { +.modal-header { display: flex; - justify-content: space-between; align-items: center; - margin-bottom: 15px; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); - padding-bottom: 10px; + gap: 20px; + margin-bottom: 20px; + padding-bottom: 15px; + border-bottom: 1px solid rgba(255, 255, 255, 0.05); } -.item-name { +.modal-icon-big { + width: 80px; + height: 80px; + background: rgba(0, 0, 0, 0.4); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.modal-icon-big img { + width: 60px; + height: 60px; + object-fit: contain; +} + +.modal-icon-big.common { + border-color: #888; +} +.modal-icon-big.rare { + border-color: #0070dd; + box-shadow: inset 0 0 10px rgba(0, 112, 221, 0.2); +} +.modal-icon-big.epic { + border-color: #a335ee; + box-shadow: inset 0 0 10px rgba(163, 53, 238, 0.2); +} +.modal-icon-big.legendary { + border-color: #ff8000; + box-shadow: inset 0 0 10px rgba(255, 128, 0, 0.2); +} + +.modal-title-group h3 { margin: 0; - font-size: 1.2rem; + font-family: "Orbitron", sans-serif; + font-size: 1.3rem; text-transform: uppercase; - letter-spacing: 1px; } -.rarity-badge { - font-size: 0.7rem; - padding: 2px 8px; - border-radius: 4px; - text-transform: uppercase; - background: rgba(255, 255, 255, 0.1); +.modal-title-group h3.common { + color: #fff; } - -.item-name.common { - color: #ffffff; +.modal-title-group h3.rare { + color: #00d2ff; } -.item-name.uncommon { - color: #1eff00; -} -.item-name.rare { - color: #0070dd; -} -.item-name.epic { +.modal-title-group h3.epic { color: #a335ee; } -.item-name.legendary { +.modal-title-group h3.legendary { color: #ff8000; } -.item-description { +.modal-raw-id { + font-size: 0.7rem; + color: #888; + margin-top: 4px; + font-family: monospace; +} + +.details-description { font-size: 0.9rem; + line-height: 1.5; color: #aaa; - line-height: 1.4; margin-bottom: 20px; + font-style: italic; +} + +.details-section h4 { + font-size: 0.8rem; + text-transform: uppercase; + color: #00d2ff; + letter-spacing: 1px; + margin-bottom: 10px; + border-left: 3px solid #00d2ff; + padding-left: 10px; } .item-stats-container { - background: rgba(0, 0, 0, 0.3); + background: rgba(0, 0, 0, 0.2); padding: 10px; - border-radius: 4px; - margin-bottom: 25px; + border-radius: 8px; } .stat-row { display: flex; justify-content: space-between; - padding: 5px 0; - font-size: 0.85rem; + padding: 8px 0; + border-bottom: 1px solid rgba(255, 255, 255, 0.03); +} + +.stat-row:last-child { + border-bottom: none; } .stat-label { - color: #00d2ff; + color: #888; + font-size: 0.85rem; display: flex; align-items: center; gap: 8px; } .stat-value { - color: #fff; + color: #00ff88; + font-family: monospace; font-weight: bold; } .btn-equip { width: 100%; padding: 12px; - background: none; + background: rgba(0, 210, 255, 0.05); border: 1px solid #00d2ff; color: #00d2ff; cursor: pointer; - text-transform: uppercase; - font-weight: bold; - letter-spacing: 1px; + font-family: "Orbitron", sans-serif; + font-size: 0.8rem; transition: all 0.2s; } .btn-equip:hover { background: #00d2ff; color: #000; - box-shadow: 0 0 15px rgba(0, 210, 255, 0.4); } .btn-equip.unequip { border-color: #ff4444; color: #ff4444; + background: rgba(255, 68, 68, 0.05); } .btn-equip.unequip:hover { background: #ff4444; color: #fff; } + +.modal-close { + position: absolute; + top: 15px; + right: 15px; + background: none; + border: none; + color: #444; + font-size: 24px; + cursor: pointer; +} + +@keyframes modalSlideUp { + from { + transform: translateY(20px); + opacity: 0; + } + to { + transform: translateY(0); + opacity: 1; + } +} diff --git a/client/src/views/GameInterface/tabs/components/ItemModal.jsx b/client/src/views/GameInterface/tabs/components/ItemModal.jsx index 4fd4a75..599cc29 100644 --- a/client/src/views/GameInterface/tabs/components/ItemModal.jsx +++ b/client/src/views/GameInterface/tabs/components/ItemModal.jsx @@ -1,5 +1,6 @@ import React from "react"; import "./ItemModal.css"; +import { getServerUrl } from "../../../../config/api"; const ItemModal = ({ item, @@ -12,23 +13,45 @@ const ItemModal = ({ }) => { if (!item) return null; + const CONNECT_URL = getServerUrl(); + const ASSET_BASE_URL = `${CONNECT_URL}/static/`; + + const getFullTextureUrl = (path) => { + if (!path) return "/assets/no-image.png"; + if (path.startsWith("http")) return path; + return `${ASSET_BASE_URL}${path}`; + }; + return (
-
e.stopPropagation()}> +
e.stopPropagation()} + > -
-
-

- {item.displayName || item.name} -

- {item.rarity} +
+
+ {item.displayName}
+
+

{item.displayName || item.name}

+
+ {item.rarity?.toUpperCase()} SYSTEM_ID: {item.id} +
+
+
-

{item.description}

+
+

{item.description}

+
+
+

+ Technical Specs +

{item.stats && Object.entries(item.stats).map(([statName, value]) => ( @@ -43,7 +66,9 @@ const ItemModal = ({
))}
+
+
{isEquipped ? ( ) : ( item.canEquip && ( diff --git a/client/src/views/GameInterface/tabs/styles/ChatTab.css b/client/src/views/GameInterface/tabs/styles/ChatTab.css index cea5596..f8ee1aa 100644 --- a/client/src/views/GameInterface/tabs/styles/ChatTab.css +++ b/client/src/views/GameInterface/tabs/styles/ChatTab.css @@ -194,6 +194,9 @@ .message { font-size: 13px; line-height: 1.4; + min-height: min-content; + padding: 4px 0; + display: block; } .msg-time { @@ -214,7 +217,12 @@ .message.system .msg-text { color: #888; + word-break: break-all; + overflow-wrap: anywhere; + display: inline-block; font-style: italic; + white-space: pre-wrap; + max-width: 100%; } .chat-input-area { @@ -411,3 +419,29 @@ color: #ff3e3e; text-shadow: 0 0 8px rgba(255, 62, 62, 0.4); } + +.message { + font-size: 13px; + line-height: 1.4; + min-height: min-content; + padding: 4px 0; + display: block; + word-wrap: break-word; +} + +.msg-text { + color: #fff; + word-break: break-all; + overflow-wrap: anywhere; + white-space: pre-wrap; + display: inline; +} + +.message.system .msg-author { + color: #ff3e3e; +} + +.message.system .msg-text { + color: #888; + font-style: italic; +}