This repository has been archived on 2026-05-04. You can view files and clone it, but cannot push or open issues or pull requests.
Galaxy-Strike-Online/client/src/views/GameInterface/tabs/components/CraftModal.jsx
2026-04-21 08:48:52 +03:00

164 lines
5.0 KiB
JavaScript

import React from "react";
import "./CraftModal.css";
import { getServerUrl } from "../../../../config/api";
const CraftModal = ({
recipe,
onClose,
onStartCraft,
activeCraft,
getOwnedAmount,
}) => {
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";
return path.startsWith("http") ? path : `${ASSET_BASE_URL}${path}`;
};
const isBusy = !!activeCraft;
const outputQty = Object.values(recipe.output || {})[0] || 1;
const canAfford = recipe.ingredients?.every(
(ing) => getOwnedAmount(ing.itemId) >= ing.quantity,
);
return (
<div className="craft-modal-overlay" onClick={onClose}>
<div className="craft-modal" onClick={(e) => e.stopPropagation()}>
<button className="close-btn-top" onClick={onClose}>
&times;
</button>
{/* Header: Icon + Title */}
<div className="modal-header-compact">
<div className="item-icon-box">
<img
src={getFullTextureUrl(recipe.texture)}
alt={recipe.displayName}
/>
<div
className="item-qty-badge"
style={{
position: "absolute",
bottom: "-5px",
right: "-5px",
background: "#00d2ff",
color: "#000",
fontSize: "10px",
padding: "2px 5px",
borderRadius: "3px",
fontWeight: "bold",
}}
>
x{outputQty}
</div>
</div>
<div className="item-info-title">
<span className="item-tag">PROTOTYPE_UNIT</span>
<h3>{recipe.displayName}</h3>
</div>
</div>
{/* Description */}
<div className="details-section">
<p className="description-text">
{recipe.description ||
"Advanced composite material for high-tier construction."}
</p>
</div>
{/* Resources */}
<div className="details-section">
<span className="section-label">Required Materials</span>
<div className="res-container">
{recipe.ingredients?.map((ing) => {
const owned = getOwnedAmount(ing.itemId);
const hasEnough = owned >= ing.quantity;
return (
<div key={ing.itemId} className="res-row">
<span className="res-name">
<i
className={`fas fa-square`}
style={{
fontSize: "8px",
color: hasEnough ? "#00ff88" : "#ff4444",
}}
></i>
{ing.displayName}
</span>
<span
className={`res-amount ${hasEnough ? "val-good" : "val-bad"}`}
>
{owned} / {ing.quantity}
</span>
</div>
);
})}
</div>
</div>
{/* Outcome Info */}
<div className="outcome-bar">
<span>
Production Time: <strong>{recipe.time_seconds}s</strong>
</span>
</div>
{/* Action Button */}
<div className="modal-footer-minimal">
{activeCraft && activeCraft.recipeId === recipe.id ? (
<div style={{ marginTop: "15px" }}>
<div
style={{
fontSize: "12px",
color: "#00d2ff",
marginBottom: "5px",
textAlign: "center",
}}
>
Constructing... {activeCraft.timeLeft}s
</div>
<div
className="progress-bar-bg"
style={{
height: "4px",
background: "rgba(255,255,255,0.1)",
borderRadius: "2px",
overflow: "hidden",
}}
>
<div
className="progress-bar-fill"
style={{
width: `${((activeCraft.totalTime - activeCraft.timeLeft) / activeCraft.totalTime) * 100}%`,
height: "100%",
background: "#00d2ff",
boxShadow: "0 0 10px #00d2ff",
}}
></div>
</div>
</div>
) : (
<button
className="btn-craft-action btn-primary-craft"
disabled={!canAfford || isBusy}
onClick={() => canAfford && !isBusy && onStartCraft(recipe)}
>
{isBusy
? "System Busy"
: !canAfford
? "Low Resources"
: "Begin Construction"}
</button>
)}
</div>
</div>
</div>
);
};
export default CraftModal;