Files
red-valley/docs/mock_jobcenter.html

789 lines
24 KiB
HTML
Raw Permalink Normal View History

2026-03-29 21:41:17 +03:00
<!DOCTYPE html>
<html lang="ro">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RV — Job Center Simulator</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', sans-serif;
user-select: none;
}
body {
width: 100vw;
height: 100vh;
background: transparent;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
/* ====== JOB CENTER PANEL (matches 17mov theme) ====== */
.jc-wrapper {
display: flex;
gap: 16px;
max-width: 1000px;
width: 100%;
height: 520px;
animation: jcFadeIn 0.3s ease-out;
}
@keyframes jcFadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Sidebar / Categories */
.jc-sidebar {
width: 350px;
background: #0D0F11;
border: 1.5px solid #121416;
border-radius: 6px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.jc-sidebar-header {
padding: 20px;
border-bottom: 1px solid #121416;
display: flex;
align-items: center;
gap: 10px;
}
.jc-sidebar-header h2 {
font-size: 22px;
font-weight: 800;
}
.jc-sidebar-header .accent {
color: #ff1a35;
}
.jc-search {
margin: 12px 16px;
height: 40px;
background: #0B0D0F;
border: 1.5px solid #121416;
border-radius: 6px;
padding: 0 14px;
color: white;
font-size: 14px;
outline: none;
width: calc(100% - 32px);
transition: border-color 0.3s;
}
.jc-search:focus {
border-color: #ff1a35;
}
.jc-search::placeholder {
color: #898989;
}
.jc-categories {
padding: 8px;
display: flex;
flex-direction: column;
gap: 4px;
overflow-y: auto;
flex: 1;
}
.jc-cat-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
}
.jc-cat-item:hover {
background: #101214;
}
.jc-cat-item.active {
background: #ff1a35;
}
.jc-cat-item .cat-icon {
width: 40px;
height: 40px;
border-radius: 6px;
background: #101214;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
}
.jc-cat-item.active .cat-icon {
background: rgba(255,255,255,0.15);
}
.jc-cat-item .cat-info h4 {
font-size: 14px;
font-weight: 600;
}
.jc-cat-item .cat-info span {
font-size: 11px;
color: #898989;
}
.jc-cat-item.active .cat-info span {
color: rgba(255,255,255,0.7);
}
/* Main Content / Job Details */
.jc-main {
flex: 1;
background: #0D0F11;
border: 1.5px solid #121416;
border-radius: 6px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.jc-job-header {
height: 156px;
background: linear-gradient(to bottom, rgba(13,15,17,0), rgba(13,15,17,1)),
linear-gradient(135deg, #1a1a2e, #16213e);
display: flex;
align-items: flex-end;
padding: 20px;
position: relative;
}
.jc-job-header .job-icon-lg {
width: 64px;
height: 64px;
border-radius: 6px;
background: #101214;
border: 1.5px solid #121416;
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
}
.jc-job-header .job-title {
margin-left: 16px;
}
.jc-job-header .job-title h2 {
font-size: 26px;
font-weight: 800;
}
.jc-job-header .job-title .job-tag {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 13px;
color: #898989;
}
.jc-job-header .job-title .job-tag .dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #ff1a35;
}
.jc-job-body {
flex: 1;
padding: 20px;
overflow-y: auto;
}
.jc-info-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
margin-bottom: 20px;
}
.jc-info-card {
background: #0E1012;
border: 1px solid #121416;
border-radius: 6px;
padding: 14px;
}
.jc-info-card .label {
font-size: 11px;
color: #898989;
text-transform: uppercase;
font-weight: 600;
}
.jc-info-card .value {
font-size: 20px;
font-weight: 800;
margin-top: 4px;
}
.jc-info-card .value .accent {
color: #ff1a35;
}
.jc-desc {
font-size: 13px;
color: #898989;
line-height: 1.6;
margin-bottom: 20px;
}
.jc-req {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 14px;
background: #0E1012;
border: 1px solid #121416;
border-radius: 6px;
margin-bottom: 12px;
}
.jc-req .req-icon {
font-size: 16px;
}
.jc-req .req-text {
font-size: 13px;
font-weight: 500;
}
.jc-req .req-status {
margin-left: auto;
font-size: 12px;
font-weight: 600;
padding: 3px 10px;
border-radius: 4px;
}
.req-ok { background: rgba(34, 197, 94, 0.15); color: #22c55e; }
.req-fail { background: rgba(255, 26, 53, 0.15); color: #ff1a35; }
/* Footer */
.jc-footer {
padding: 16px 20px;
border-top: 1px solid #121416;
display: flex;
gap: 8px;
}
.jc-btn {
flex: 1;
height: 42px;
border: none;
border-radius: 6px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
transition: all 0.3s;
}
.jc-btn-apply {
background: #ff1a35;
color: white;
}
.jc-btn-apply:hover {
opacity: 0.85;
}
.jc-btn-close {
background: #101214;
color: #898989;
border: 1.5px solid #121416;
}
.jc-btn-close:hover {
background: #1f2225;
color: white;
}
/* ====== LICENSE DIALOG OVERLAY ====== */
.license-overlay {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: rgba(0,0,0,0.7);
display: none;
align-items: center;
justify-content: center;
z-index: 50;
animation: fadeIn 0.2s ease-out;
}
.license-overlay.active {
display: flex;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(20px) scale(0.95); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
.license-dialog {
background: #0D0F11;
border: 1.5px solid #121416;
border-radius: 6px;
width: 380px;
overflow: hidden;
animation: slideUp 0.3s ease-out;
box-shadow: 0 25px 60px rgba(0,0,0,0.5);
}
.ld-header {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
padding: 18px 20px 14px;
border-bottom: 1px solid #1a1c1e;
position: relative;
}
.ld-icon {
width: 36px;
height: 36px;
background: rgba(255,26,53,0.12);
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
}
.ld-icon svg { width: 20px; height: 20px; fill: #ff1a35; }
.ld-header h2 {
font-size: 18px;
font-weight: 700;
}
.ld-close-x {
position: absolute;
right: 16px; top: 50%;
transform: translateY(-50%);
width: 28px; height: 28px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 4px;
transition: background 0.2s;
}
.ld-close-x:hover { background: #1f2225; }
.ld-close-x svg { width: 14px; height: 14px; stroke: #898989; transition: stroke 0.2s; }
.ld-close-x:hover svg { stroke: white; }
.ld-body {
padding: 20px;
text-align: center;
}
.ld-body p { font-size: 14px; color: #898989; line-height: 1.6; }
.ld-body .highlight {
display: block;
margin: 12px 0;
font-size: 15px;
font-weight: 700;
color: #ff1a35;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.ld-body .sub-text { font-size: 13px; color: #898989; }
.ld-footer {
display: flex;
gap: 8px;
padding: 4px 20px 20px;
}
.ld-btn {
flex: 1;
height: 42px;
border: none;
border-radius: 6px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.ld-btn-close {
background: #222528;
color: #e0e0e0;
border: 1.5px solid #3a3d40;
}
.ld-btn-close:hover { background: #33363a; color: white; border-color: #4a4d50; }
.ld-btn-route {
background: #ff1a35;
color: white;
}
.ld-btn-route:hover { opacity: 0.85; }
.ld-btn-route svg { width: 14px; height: 14px; fill: white; }
/* Success notification */
.success-toast {
position: fixed;
top: 30px;
left: 50%;
transform: translateX(-50%) translateY(-100px);
background: #0D0F11;
border: 1.5px solid #22c55e;
border-radius: 6px;
padding: 14px 24px;
display: flex;
align-items: center;
gap: 10px;
font-size: 14px;
font-weight: 600;
z-index: 60;
transition: transform 0.4s ease;
box-shadow: 0 10px 40px rgba(0,0,0,0.4);
}
.success-toast.show {
transform: translateX(-50%) translateY(0);
}
.success-toast .s-icon {
width: 32px; height: 32px;
border-radius: 6px;
background: rgba(34,197,94,0.15);
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
/* Player state bar */
.player-bar {
position: fixed;
top: 12px;
right: 12px;
display: flex;
gap: 8px;
z-index: 100;
}
.player-toggle {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 14px;
background: #0D0F11;
border: 1.5px solid #121416;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
cursor: pointer;
transition: border-color 0.2s;
}
.player-toggle:hover {
border-color: #2a2d30;
}
.pt-switch {
width: 36px;
height: 20px;
background: #333;
border-radius: 10px;
position: relative;
transition: background 0.2s;
}
.pt-switch::after {
content: '';
position: absolute;
width: 14px; height: 14px;
left: 3px; top: 3px;
background: white;
border-radius: 50%;
transition: transform 0.2s;
}
.player-toggle.on .pt-switch {
background: #22c55e;
}
.player-toggle.on .pt-switch::after {
transform: translateX(16px);
}
</style>
</head>
<body>
<!-- Player State Bar -->
<div class="player-bar">
<div class="player-toggle" id="licenseToggle" onclick="toggleState('license')">
🪪 Permis
<div class="pt-switch"></div>
</div>
</div>
<!-- Job Center UI -->
<div class="jc-wrapper" id="jobCenter">
<!-- Sidebar -->
<div class="jc-sidebar">
<div class="jc-sidebar-header">
<h2>Job <span class="accent">Center</span></h2>
</div>
<input class="jc-search" type="text" placeholder="Caută un job...">
<div class="jc-categories">
<div class="jc-cat-item active" data-job="garbage" onclick="selectJob('garbage')">
<div class="cat-icon">🗑️</div>
<div class="cat-info">
<h4>Garbage Collector</h4>
<span>Colectare gunoi</span>
</div>
</div>
<div class="jc-cat-item" data-job="deliverer" onclick="selectJob('deliverer')">
<div class="cat-icon">📦</div>
<div class="cat-info">
<h4>Deliverer</h4>
<span>Livrări în oraș</span>
</div>
</div>
<div class="jc-cat-item" data-job="postman" onclick="selectJob('postman')">
<div class="cat-icon">✉️</div>
<div class="cat-info">
<h4>Postman</h4>
<span>Livrare colete</span>
</div>
</div>
<div class="jc-cat-item" data-job="lumberjack" onclick="selectJob('lumberjack')">
<div class="cat-icon">🪓</div>
<div class="cat-info">
<h4>Lumberjack</h4>
<span>Tăiere lemne</span>
</div>
</div>
<div class="jc-cat-item" data-job="bus" onclick="selectJob('bus')">
<div class="cat-icon">🚌</div>
<div class="cat-info">
<h4>Bus Driver</h4>
<span>Transport public</span>
</div>
</div>
<div class="jc-cat-item" data-job="miner" onclick="selectJob('miner')">
<div class="cat-icon">⛏️</div>
<div class="cat-info">
<h4>Miner</h4>
<span>Extracție minereu</span>
</div>
</div>
<div class="jc-cat-item" data-job="electrician" onclick="selectJob('electrician')">
<div class="cat-icon"></div>
<div class="cat-info">
<h4>Electrician</h4>
<span>Reparații electrice</span>
</div>
</div>
</div>
</div>
<!-- Main content -->
<div class="jc-main" id="jobDetail">
</div>
</div>
<!-- License Dialog Overlay -->
<div class="license-overlay" id="licenseDialog">
<div class="license-dialog">
<div class="ld-header">
<div class="ld-icon">
<svg viewBox="0 0 24 24"><path d="M12 2L1 21h22L12 2zm0 4l7.53 13H4.47L12 6zm-1 4v4h2v-4h-2zm0 6v2h2v-2h-2z"/></svg>
</div>
<h2>Permis Necesar</h2>
<div class="ld-icon">
<svg viewBox="0 0 24 24"><path d="M12 2L1 21h22L12 2zm0 4l7.53 13H4.47L12 6zm-1 4v4h2v-4h-2zm0 6v2h2v-2h-2z"/></svg>
</div>
<div class="ld-close-x" onclick="closeLicenseDialog()">
<svg viewBox="0 0 24 24" fill="none"><path d="M18 6L6 18M6 6l12 12" stroke-width="2" stroke-linecap="round"/></svg>
</div>
</div>
<div class="ld-body">
<p>Acest job necesită conducerea unui vehicul.</p>
<span class="highlight">Nu ai permis de conducere.</span>
<p class="sub-text">Mergi la Școala de Șoferi pentru a obține unul.</p>
</div>
<div class="ld-footer">
<button class="ld-btn ld-btn-close" onclick="closeLicenseDialog()">Închide</button>
<button class="ld-btn ld-btn-route" onclick="routeToSchool()">
<svg viewBox="0 0 24 24"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>
Rută Școala de Șoferi
</button>
</div>
</div>
</div>
<!-- Success Toast -->
<div class="success-toast" id="successToast">
<div class="s-icon"></div>
<span id="successText"></span>
</div>
<script>
// ====== STATE ======
const state = {
license: false,
selectedJob: 'garbage'
};
const jobs = {
garbage: { name: "Garbage Collector", icon: "🗑️", salary: "$150", xp: "25", level: "0", desc: "Colectezi gunoiul din oraș cu un camion special. Necesită permis de conducere pentru operarea vehiculului de serviciu.", needsLicense: true },
deliverer: { name: "Deliverer", icon: "📦", salary: "$120", xp: "20", level: "0", desc: "Livrezi colete și pachete în diferite locații din oraș. Necesită permis pentru vehiculul de livrare.", needsLicense: true },
postman: { name: "Postman", icon: "✉️", salary: "$110", xp: "18", level: "0", desc: "Distribui corespondența și pachetele poștale în cartierele din Los Santos.", needsLicense: true },
lumberjack: { name: "Lumberjack", icon: "🪓", salary: "$180", xp: "30", level: "0", desc: "Tai și transporti lemne din pădurea de lângă oraș. Vehicul necesar pentru transport.", needsLicense: true },
bus: { name: "Bus Driver", icon: "🚌", salary: "$200", xp: "35", level: "0", desc: "Conduci autobuzul pe rute fixe în oraș, transportând pasageri. Necesită permis de conducere.", needsLicense: true },
miner: { name: "Miner", icon: "⛏️", salary: "$160", xp: "28", level: "0", desc: "Extragi minereu și pietre prețioase în mina abandonată. Nu necesită vehicul.", needsLicense: false },
electrician: { name: "Electrician", icon: "⚡", salary: "$140", xp: "22", level: "0", desc: "Repari instalații electrice în clădirile din oraș. Lucru pe jos, fără vehicul.", needsLicense: false }
};
// ====== SELECT JOB ======
function selectJob(jobId) {
state.selectedJob = jobId;
// Update sidebar
document.querySelectorAll('.jc-cat-item').forEach(el => {
el.classList.toggle('active', el.dataset.job === jobId);
});
renderJobDetail();
}
function renderJobDetail() {
const job = jobs[state.selectedJob];
const detail = document.getElementById('jobDetail');
const hasLicense = state.license;
detail.innerHTML = `
<div class="jc-job-header">
<div class="job-icon-lg">${job.icon}</div>
<div class="job-title">
<h2>${job.name}</h2>
<span class="job-tag"><span class="dot"></span> Job Civil</span>
</div>
</div>
<div class="jc-job-body">
<div class="jc-info-grid">
<div class="jc-info-card">
<div class="label">Salariu</div>
<div class="value"><span class="accent">${job.salary}</span></div>
</div>
<div class="jc-info-card">
<div class="label">XP / Livrare</div>
<div class="value">${job.xp}</div>
</div>
<div class="jc-info-card">
<div class="label">Level Necesar</div>
<div class="value">${job.level}</div>
</div>
</div>
<p class="jc-desc">${job.desc}</p>
${job.needsLicense ? `
<div class="jc-req">
<span class="req-icon">🪪</span>
<span class="req-text">Permis de conducere</span>
<span class="req-status ${hasLicense ? 'req-ok' : 'req-fail'}">${hasLicense ? '✓ Deținut' : '✗ Lipsă'}</span>
</div>
` : ''}
</div>
<div class="jc-footer">
<button class="jc-btn jc-btn-close" onclick="closeJobCenter()">Închide</button>
<button class="jc-btn jc-btn-apply" onclick="applyJob()">Aplică</button>
</div>
`;
}
// ====== APPLY ======
function applyJob() {
const job = jobs[state.selectedJob];
if (job.needsLicense && !state.license) {
// Show license dialog
document.getElementById('licenseDialog').classList.add('active');
return;
}
// Success!
showSuccess(`Ai fost angajat ca ${job.name}!`);
}
function closeLicenseDialog() {
document.getElementById('licenseDialog').classList.remove('active');
}
function routeToSchool() {
closeLicenseDialog();
showSuccess('Waypoint setat pe Școala de Șoferi! (214.45, -1400.163)');
}
function closeJobCenter() {
// In simulator, just flash a message
showSuccess('Job Center închis (ESC)');
}
function showSuccess(text) {
const toast = document.getElementById('successToast');
document.getElementById('successText').textContent = text;
toast.classList.add('show');
setTimeout(() => toast.classList.remove('show'), 3000);
}
// ====== TOGGLE STATE ======
function toggleState(key) {
state[key] = !state[key];
const el = document.getElementById(key + 'Toggle');
el.classList.toggle('on', state[key]);
renderJobDetail(); // Update req status
}
// ====== NUI MESSAGE LISTENER (for simulator integration) ======
window.addEventListener("message", function(event) {
if (event.data.action === "show") {
document.getElementById('jobCenter').style.display = 'flex';
}
if (event.data.action === "hide") {
document.getElementById('jobCenter').style.display = 'none';
}
});
// Init
renderJobDetail();
</script>
</body>
</html>