interests showcase in files
This commit is contained in:
parent
b574e2531c
commit
3c0cc155dc
127
cv.json
127
cv.json
@ -1,127 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "David Hrdina Němeček",
|
|
||||||
"photo": "photo.png",
|
|
||||||
"headline": "Principal Software Engineer at Oracle NetSuite",
|
|
||||||
"summary": "Working on the UI platform architecture for 40k+ companies. Focused on AI-assisted engineering, observability, and performance.",
|
|
||||||
"email": "explosive@dejvino.cz",
|
|
||||||
"location": "Brno, Czechia",
|
|
||||||
"phone": "+420 775 26 26 32",
|
|
||||||
"contact_links": {
|
|
||||||
"Website": "https://www.dejvino.cz",
|
|
||||||
"Email": "mailto:explosive@dejvino.cz",
|
|
||||||
"Resume": "https://dejvino.cz/cv"
|
|
||||||
},
|
|
||||||
"about": [
|
|
||||||
"Principal Software Engineer at Oracle NetSuite, working on the UI platform for 40k+ companies."
|
|
||||||
],
|
|
||||||
"highlights": [
|
|
||||||
{
|
|
||||||
"title": "Telemetry stack architecture",
|
|
||||||
"description": [
|
|
||||||
"Shaped telemetry direction across user behavior and performance.",
|
|
||||||
"Designed and rolled out a custom OpenTelemetry-based tracing library to gain rich and reliable insights across multiple front-ends and back-end."
|
|
||||||
],
|
|
||||||
"date": "2024 – 2026"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "UI performance optimizations",
|
|
||||||
"description": "Tiered JS bundle dependency loading for shorter page load times.",
|
|
||||||
"date": "2025 – 2026"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outside_work": [
|
|
||||||
"Mandolin",
|
|
||||||
"Synthwave",
|
|
||||||
"Electronics",
|
|
||||||
"3D Printing",
|
|
||||||
"Mountain Biking"
|
|
||||||
],
|
|
||||||
"experience": [
|
|
||||||
{
|
|
||||||
"title": "Principal Software Engineer (UI Platform Architecture)",
|
|
||||||
"company": "Oracle|NetSuite",
|
|
||||||
"date": "2023 – present",
|
|
||||||
"description": "UI Architect working on feature discovery, solution prototyping and technical designs. Mainly focused on UI telemetry, performance, CI/CD tooling and pipelines."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Senior Software Development Manager (UI Platform)",
|
|
||||||
"company": "Oracle|NetSuite",
|
|
||||||
"date": "2022 – 2023",
|
|
||||||
"description": "Engineering lead for multiple UI Platform teams who designed, developed and released a UI framework and tooling used by the rest of the organization. Leader of a UI testing architecture group responsible for defining a testing strategy across the UI Platform."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Software Development Manager (UI Platform)",
|
|
||||||
"company": "Oracle|NetSuite",
|
|
||||||
"date": "2020 – 2022",
|
|
||||||
"description": "Engineering lead for a UI Platform team who developed components for a UI toolkit used by the rest of the organization. Technical product owner while bootstrapping a team."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Software Development Manager (ERP, Tax)",
|
|
||||||
"company": "Oracle|NetSuite",
|
|
||||||
"date": "2017 – 2020",
|
|
||||||
"description": "Lead developer for ERP: Tax. Design and implementation of a pluggable Tax calculation engine. Coordination of multiple squads supporting both the legacy and the next-gen systems concurrently."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Senior Software Engineer (ERP, Tax)",
|
|
||||||
"company": "Oracle|NetSuite",
|
|
||||||
"date": "2013 – 2017",
|
|
||||||
"description": "Development of Tax calculation and reporting modules in a cloud ERP system. Large-scale refactoring of legacy code. Introduction of a pluggable architecture."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Software Engineer",
|
|
||||||
"company": "Q2 Interactive",
|
|
||||||
"date": "2009 – 2013",
|
|
||||||
"description": "Development and project leadership of multiple web applications and services: CRM system (PHP backend server, JavaScript frontend, Android client app), Accounting web app (PHP, JavaScript), e-commerce sites (Magento) and Linux server maintenance."
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"skills": {
|
|
||||||
"Main": [
|
|
||||||
"TypeScript",
|
|
||||||
"Java",
|
|
||||||
"Linux",
|
|
||||||
"NodeJs"
|
|
||||||
],
|
|
||||||
"Support": [
|
|
||||||
"Kotlin",
|
|
||||||
"Go",
|
|
||||||
"JavaScript",
|
|
||||||
"Oracle",
|
|
||||||
"SQL",
|
|
||||||
"Git",
|
|
||||||
"React",
|
|
||||||
"Preact",
|
|
||||||
"Python"
|
|
||||||
],
|
|
||||||
"Languages": [
|
|
||||||
"Czech (native)",
|
|
||||||
"English (proficient)",
|
|
||||||
"German (elementary)"
|
|
||||||
],
|
|
||||||
"Other": [
|
|
||||||
"C/C++",
|
|
||||||
"Supercomputers",
|
|
||||||
"OpenMPI",
|
|
||||||
"Visualization",
|
|
||||||
"Data science",
|
|
||||||
"Embedded",
|
|
||||||
"OpenSCAD"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"education": [
|
|
||||||
{
|
|
||||||
"degree": "Master's degree",
|
|
||||||
"field": "Parallel and Distributed Systems",
|
|
||||||
"institution": "Faculty of Informatics, Masaryk University Brno",
|
|
||||||
"date": "2011 – 2013",
|
|
||||||
"thesis": "Efficient computation and visualization of correlations in medical signals. The first part consisted of high-performance computation of correlations on large volumes of analog data using supercomputers. The second part covered the visualization of the computed results which allowed interactive exploration and processing of the data by a researcher."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"degree": "Bachelor's degree",
|
|
||||||
"field": "Parallel and Distributed Systems",
|
|
||||||
"institution": "Faculty of Informatics, Masaryk University Brno",
|
|
||||||
"date": "2008 – 2011",
|
|
||||||
"thesis": "Parallel implementation of force-field decompression algorithm. The solution executed on a supercomputer cluster to perform real-time simulation of molecular forces. This in turn provided haptic feedback to a 3D pointing device."
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"philosophy": "I design platform layers that stay out of the way while enabling everything else. Quiet infrastructure. Measurable value."
|
|
||||||
}
|
|
||||||
111
index.php
111
index.php
@ -20,6 +20,32 @@ $nav_links = [
|
|||||||
];
|
];
|
||||||
$highlights = $cvData['highlights'] ?? [];
|
$highlights = $cvData['highlights'] ?? [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sourced Interests Showcase (from filesystem)
|
||||||
|
*/
|
||||||
|
$interests_showcase = [];
|
||||||
|
$interests_base = __DIR__ . '/interests';
|
||||||
|
if (is_dir($interests_base)) {
|
||||||
|
$folders = glob($interests_base . '/*', GLOB_ONLYDIR);
|
||||||
|
if ($folders) {
|
||||||
|
foreach ($folders as $folder) {
|
||||||
|
$config_path = $folder . '/interest.json';
|
||||||
|
$config = [];
|
||||||
|
if (file_exists($config_path)) {
|
||||||
|
$config = json_decode(file_get_contents($config_path), true);
|
||||||
|
}
|
||||||
|
$img_file = $config['image'] ?? 'image.png';
|
||||||
|
$has_image = file_exists($folder . '/' . $img_file);
|
||||||
|
|
||||||
|
$interests_showcase[] = [
|
||||||
|
'name' => $config['name'] ?? basename($folder),
|
||||||
|
'image' => $has_image ? 'interests/' . basename($folder) . '/' . $img_file : null,
|
||||||
|
'caption' => $config['caption'] ?? ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$site_url = "https://www.dejvino.cz/";
|
$site_url = "https://www.dejvino.cz/";
|
||||||
$site_title = $name;
|
$site_title = $name;
|
||||||
$site_desc = "$name - $headline";
|
$site_desc = "$name - $headline";
|
||||||
@ -202,6 +228,41 @@ $cv_skills = $cvData['cv']['skills'] ?? [];
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<?php if ($interests_showcase): ?>
|
||||||
|
<?php // Hardcoded palette of dark, varied tints
|
||||||
|
$bg_palette = [
|
||||||
|
'#1e2a33', // Dark Blue
|
||||||
|
'#1e332a', // Dark Green
|
||||||
|
'#2a1e33', // Dark Purple
|
||||||
|
'#331e2a', // Dark Red
|
||||||
|
'#1a3333', // Dark Teal
|
||||||
|
'#33331a', // Dark Olive
|
||||||
|
];
|
||||||
|
$palette_size = count($bg_palette);
|
||||||
|
?>
|
||||||
|
<section class="card interests-showcase">
|
||||||
|
<nav class="interests-nav">
|
||||||
|
<h2>Things I like to do</h2>
|
||||||
|
<ul>
|
||||||
|
<?php foreach ($interests_showcase as $i => $item): ?>
|
||||||
|
<li class="<?= $i === 0 ? 'active' : '' ?>" data-index="<?= $i ?>">
|
||||||
|
<?= htmlspecialchars($item['name']) ?>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<div class="interests-display">
|
||||||
|
<?php foreach ($interests_showcase as $i => $item): ?>
|
||||||
|
<div class="interest-slide <?= $i === 0 ? 'active' : '' ?>" data-index="<?= $i ?>" style="background-color: <?= $bg_palette[$i % $palette_size] ?>;">
|
||||||
|
<?php if ($item['image']): ?>
|
||||||
|
<img src="<?= htmlspecialchars($item['image']) ?>" alt="<?= htmlspecialchars($item['name']) ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
<p class="caption"><?= htmlspecialchars($item['caption']) ?></p>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ($isCvPath && $highlights): ?>
|
<?php if ($isCvPath && $highlights): ?>
|
||||||
<section class="card selected-work">
|
<section class="card selected-work">
|
||||||
@ -226,28 +287,6 @@ $cv_skills = $cvData['cv']['skills'] ?? [];
|
|||||||
</section>
|
</section>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ($cvData['outside_work'] ?? []): ?>
|
|
||||||
<?php if ($isCvPath): ?>
|
|
||||||
<section class="card personal">
|
|
||||||
<h2>Outside Work</h2>
|
|
||||||
<div class="personal-tags">
|
|
||||||
<?php foreach ($cvData['outside_work'] as $tag): ?>
|
|
||||||
<span class="personal-tag"><?= $tag ?></span>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<?php else: ?>
|
|
||||||
<section class="card personal">
|
|
||||||
<h2>Interests</h2>
|
|
||||||
<div class="personal-tags">
|
|
||||||
<?php foreach ($cvData['outside_work'] as $tag): ?>
|
|
||||||
<span class="personal-tag"><?= $tag ?></span>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if ($isCvPath): ?>
|
<?php if ($isCvPath): ?>
|
||||||
<section class="card cv-container">
|
<section class="card cv-container">
|
||||||
<div class="cv-content">
|
<div class="cv-content">
|
||||||
@ -329,6 +368,34 @@ $cv_skills = $cvData['cv']['skills'] ?? [];
|
|||||||
const el = document.getElementById("contact-mail");
|
const el = document.getElementById("contact-mail");
|
||||||
if (el) el.innerHTML = `<a href="mailto:${addr}">${addr}</a>`;
|
if (el) el.innerHTML = `<a href="mailto:${addr}">${addr}</a>`;
|
||||||
})('<?= base64_encode($email_user) ?>', 'dejvino', 'cz');
|
})('<?= base64_encode($email_user) ?>', 'dejvino', 'cz');
|
||||||
|
|
||||||
|
// Interests Showcase Logic
|
||||||
|
(() => {
|
||||||
|
const slides = document.querySelectorAll('.interest-slide');
|
||||||
|
const labels = document.querySelectorAll('.interests-nav li');
|
||||||
|
if (!slides.length) return;
|
||||||
|
|
||||||
|
let currentIndex = 0;
|
||||||
|
let interval = setInterval(next, 5000);
|
||||||
|
|
||||||
|
function show(index) {
|
||||||
|
slides.forEach(s => s.classList.remove('active'));
|
||||||
|
labels.forEach(l => l.classList.remove('active'));
|
||||||
|
slides[index].classList.add('active');
|
||||||
|
labels[index].classList.add('active');
|
||||||
|
currentIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
function next() { show((currentIndex + 1) % slides.length); }
|
||||||
|
|
||||||
|
labels.forEach((label, i) => {
|
||||||
|
label.addEventListener('click', () => {
|
||||||
|
show(i);
|
||||||
|
clearInterval(interval);
|
||||||
|
interval = setInterval(next, 8000); // Slower auto-switch after manual interaction
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
<!-- Cloudflare Web Analytics -->
|
<!-- Cloudflare Web Analytics -->
|
||||||
<script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "90827cb740cd4b1db611be059f64daa9"}'></script><!-- End Cloudflare Web Analytics -->
|
<script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "90827cb740cd4b1db611be059f64daa9"}'></script><!-- End Cloudflare Web Analytics -->
|
||||||
|
|||||||
5
interests/1/interest.json
Normal file
5
interests/1/interest.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "Mandolin",
|
||||||
|
"image": "image.png",
|
||||||
|
"caption": "Octave mandolin is my instrument of choice. Wide range of tones, pleasant sound. Great way to relax your mind, explore melodies and harmonies."
|
||||||
|
}
|
||||||
5
interests/3/interest.json
Normal file
5
interests/3/interest.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "Electronics tinkering",
|
||||||
|
"image": "image.png",
|
||||||
|
"caption": "Building a useful device from scratch. Retrofitting modern brains into a broken vintage shell. Electronics is the magic that makes things alive."
|
||||||
|
}
|
||||||
BIN
interests/4/image.png
Normal file
BIN
interests/4/image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 751 KiB |
5
interests/4/interest.json
Normal file
5
interests/4/interest.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "Synthwave",
|
||||||
|
"image": "image.png",
|
||||||
|
"caption": "Neon-filled nostalgia. Fun to create, relaxing to listen to it."
|
||||||
|
}
|
||||||
5
interests/5/interest.json
Normal file
5
interests/5/interest.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "3D Printing",
|
||||||
|
"image": "image.png",
|
||||||
|
"caption": ""
|
||||||
|
}
|
||||||
5
interests/6/interest.json
Normal file
5
interests/6/interest.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "Mountain Biking",
|
||||||
|
"image": "image.png",
|
||||||
|
"caption": ""
|
||||||
|
}
|
||||||
5
interests/7/interest.json
Normal file
5
interests/7/interest.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "RC Cars",
|
||||||
|
"image": "image.png",
|
||||||
|
"caption": "Rock crawlers, construction trucks, military vehicles. There is a fun challenge awaiting an RC car on every corner."
|
||||||
|
}
|
||||||
95
style.css
95
style.css
@ -129,6 +129,7 @@ body {
|
|||||||
margin-right: 16px !important;
|
margin-right: 16px !important;
|
||||||
}
|
}
|
||||||
.hero { grid-column: span 3; }
|
.hero { grid-column: span 3; }
|
||||||
|
.interests-showcase { grid-column: span 3; }
|
||||||
.hiring-toggle { grid-column: span 3; }
|
.hiring-toggle { grid-column: span 3; }
|
||||||
.selected-work { grid-column: span 2; }
|
.selected-work { grid-column: span 2; }
|
||||||
body:not(.cv-mode) .personal { grid-column: span 3; }
|
body:not(.cv-mode) .personal { grid-column: span 3; }
|
||||||
@ -1030,3 +1031,97 @@ a { color: var(--link-color); text-decoration: none; }
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Interests Showcase Styles */
|
||||||
|
.interests-showcase {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 24px !important;
|
||||||
|
min-height: 400px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interests-nav {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interests-nav h2 { margin-top: 0; font-size: 0.75rem; margin-bottom: 16px; }
|
||||||
|
.interests-nav ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interests-nav li {
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: rgba(0, 243, 255, 0.05);
|
||||||
|
border: 1px solid rgba(0, 243, 255, 0.15);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.interests-nav li:hover { background: rgba(0, 243, 255, 0.15); border-color: rgba(0, 243, 255, 0.4); }
|
||||||
|
|
||||||
|
.interests-nav li.active {
|
||||||
|
background: var(--accent-color);
|
||||||
|
color: #000;
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
font-weight: bold;
|
||||||
|
box-shadow: 0 0 15px var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.interests-display {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
min-height: 250px;
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interest-slide {
|
||||||
|
display: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
padding: 30px;
|
||||||
|
color: #fff; /* Changed to white for dark backgrounds */
|
||||||
|
}
|
||||||
|
.interest-slide.active { display: flex; animation: interestFadeIn 0.4s ease-out; }
|
||||||
|
|
||||||
|
.interest-slide img {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interest-slide .caption {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
font-size: 1.0rem;
|
||||||
|
line-height: 2.0;
|
||||||
|
color: inherit;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 1px 2px rgba(255,255,255,0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.interest-slide img + .caption {
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 0 10px #000, 0 0 20px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes interestFadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user