reformat
This commit is contained in:
parent
e7cb2ec37a
commit
319c01c59c
312
index.php
312
index.php
@ -1,8 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Content config:
|
* Content config:
|
||||||
*/
|
*/
|
||||||
$cvData = json_decode(file_get_contents(__DIR__.'/cv.json'), true);
|
$cvData = json_decode(file_get_contents(__DIR__ . '/cv.json'), true);
|
||||||
|
|
||||||
$name = $cvData['name'] ?? '';
|
$name = $cvData['name'] ?? '';
|
||||||
$site_title = $cvData['subtitle'] ?? '';
|
$site_title = $cvData['subtitle'] ?? '';
|
||||||
@ -34,7 +35,7 @@ $extra_contact_links = $cvData['contact_links'] ?? [];
|
|||||||
* CV Data
|
* CV Data
|
||||||
*/
|
*/
|
||||||
// Map experience to expected structure
|
// Map experience to expected structure
|
||||||
$cv_experience = array_map(function($e){
|
$cv_experience = array_map(function ($e) {
|
||||||
return [
|
return [
|
||||||
'title' => $e['title'] ?? '',
|
'title' => $e['title'] ?? '',
|
||||||
'org' => $e['organization'] ?? '',
|
'org' => $e['organization'] ?? '',
|
||||||
@ -44,7 +45,7 @@ $cv_experience = array_map(function($e){
|
|||||||
}, $cvData['experience'] ?? []);
|
}, $cvData['experience'] ?? []);
|
||||||
|
|
||||||
// Map education to expected structure
|
// Map education to expected structure
|
||||||
$cv_education = array_map(function($e){
|
$cv_education = array_map(function ($e) {
|
||||||
return [
|
return [
|
||||||
'title' => $e['degree'] ?? '',
|
'title' => $e['degree'] ?? '',
|
||||||
'org' => $e['institution'] ?? '',
|
'org' => $e['institution'] ?? '',
|
||||||
@ -65,7 +66,8 @@ $cv_skills = $cvData['skills'] ?? [];
|
|||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title><?= $site_title ?></title>
|
<title><?= $site_title ?></title>
|
||||||
<link rel="canonical" href="<?= $site_url ?>">
|
<link rel="canonical" href="<?= $site_url ?>">
|
||||||
@ -80,23 +82,24 @@ $cv_skills = $cvData['skills'] ?? [];
|
|||||||
<meta property="og:description" content="<?= $subtitle ?>">
|
<meta property="og:description" content="<?= $subtitle ?>">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
<?php
|
<?php
|
||||||
include 'style.css';
|
include 'style.css';
|
||||||
?>
|
?>
|
||||||
</style>
|
</style>
|
||||||
<link rel="shortcut icon" href="favicon.ico">
|
<link rel="shortcut icon" href="favicon.ico">
|
||||||
</head>
|
</head>
|
||||||
<body class="preload">
|
|
||||||
|
<body class="preload">
|
||||||
|
|
||||||
<main class="bento-grid">
|
<main class="bento-grid">
|
||||||
<section class="card profile">
|
<section class="card profile">
|
||||||
<?php
|
<?php
|
||||||
if (file_exists($photo_file)) {
|
if (file_exists($photo_file)) {
|
||||||
$avatarBase64 = base64_encode(file_get_contents($photo_file));
|
$avatarBase64 = base64_encode(file_get_contents($photo_file));
|
||||||
echo '<img src="data:image/png;base64,' . $avatarBase64 . '" alt="' . $name . '" class="avatar" width="120" height="160" />';
|
echo '<img src="data:image/png;base64,' . $avatarBase64 . '" alt="' . $name . '" class="avatar" width="120" height="160" />';
|
||||||
} else {
|
} else {
|
||||||
echo '<div class="avatar-placeholder"></div>';
|
echo '<div class="avatar-placeholder"></div>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<header class="header-text">
|
<header class="header-text">
|
||||||
<h1><?= $name ?></h1>
|
<h1><?= $name ?></h1>
|
||||||
@ -119,13 +122,13 @@ $cv_skills = $cvData['skills'] ?? [];
|
|||||||
<section class="card contact">
|
<section class="card contact">
|
||||||
<h2>Remote_Access</h2>
|
<h2>Remote_Access</h2>
|
||||||
<address class="mono-addr">
|
<address class="mono-addr">
|
||||||
Email: <span id="contact-mail">uncovering...</span>
|
Email: <span id="contact-mail">uncovering...</span>
|
||||||
</address>
|
</address>
|
||||||
<address class="mono-addr">
|
<address class="mono-addr">
|
||||||
Socials:
|
Socials:
|
||||||
<?php foreach ($extra_contact_links as $label => $url): ?>
|
<?php foreach ($extra_contact_links as $label => $url): ?>
|
||||||
<br><a href="<?= $url ?>" target="_blank"><?= $label ?></a>
|
<br><a href="<?= $url ?>" target="_blank"><?= $label ?></a>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</address>
|
</address>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -152,46 +155,43 @@ $cv_skills = $cvData['skills'] ?? [];
|
|||||||
<div class="cv-content">
|
<div class="cv-content">
|
||||||
<?php $file_mod_time = filemtime(__FILE__); ?>
|
<?php $file_mod_time = filemtime(__FILE__); ?>
|
||||||
<p class="cv-modified hidden hidden-toggle">Modified: <?= date("Y-m-d", $file_mod_time) ?></p>
|
<p class="cv-modified hidden hidden-toggle">Modified: <?= date("Y-m-d", $file_mod_time) ?></p>
|
||||||
<?php
|
<?php
|
||||||
$firstJob = $cv_experience[0] ?? null;
|
$firstJob = $cv_experience[0] ?? null;
|
||||||
if ($firstJob):
|
if ($firstJob):
|
||||||
?>
|
?>
|
||||||
<section class="cv-section first-experience hidden hidden-toggle">
|
<section class="cv-section first-experience hidden hidden-toggle">
|
||||||
<h2>Latest Experience</h2>
|
<h2>Latest Experience</h2>
|
||||||
<article class="cv-item">
|
<article class="cv-item">
|
||||||
<header class="cv-item-header">
|
<header class="cv-item-header">
|
||||||
<h3 class="cv-title"><?= $firstJob['title'] ?></h3>
|
<h3 class="cv-title"><?= $firstJob['title'] ?></h3>
|
||||||
<time class="cv-date"><?= $firstJob['date'] ?></time>
|
<time class="cv-date"><?= $firstJob['date'] ?></time>
|
||||||
</header>
|
</header>
|
||||||
<p class="cv-org"><?= $firstJob['org'] ?></p>
|
<p class="cv-org"><?= $firstJob['org'] ?></p>
|
||||||
<p class="cv-desc"><?= $firstJob['desc'] ?></p>
|
<p class="cv-desc"><?= $firstJob['desc'] ?></p>
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<section class="cv-section skills hidden hidden-toggle">
|
<section class="cv-section skills hidden hidden-toggle">
|
||||||
<h2>Skills</h2>
|
<h2>Skills</h2>
|
||||||
<div class="skill-categories">
|
<div class="skill-categories">
|
||||||
<?php
|
<?php
|
||||||
$global_i = 0;
|
$global_i = 0;
|
||||||
foreach ($cv_skills as $category => $skills): ?>
|
foreach ($cv_skills as $category => $skills): ?>
|
||||||
<div class="skill-group">
|
<div class="skill-group">
|
||||||
<h3><?= $category ?></h3>
|
<h3><?= $category ?></h3>
|
||||||
<div class="skill-tags">
|
<div class="skill-tags">
|
||||||
<?php foreach ($skills as $skill):
|
<?php foreach ($skills as $skill):
|
||||||
$fontSize = 0.85 + (($global_i * 3) % 5) * 0.2;
|
$fontSize = 0.85 + (($global_i * 3) % 5) * 0.2;
|
||||||
$opacity = 0.6 + (($global_i * 2) % 4) * 0.1;
|
$opacity = 0.6 + (($global_i * 2) % 4) * 0.1;
|
||||||
?>
|
?>
|
||||||
<span class="tag" style="transition-delay: <?= 0.6 + ($global_i * 0.05) ?>s; font-size: <?= $fontSize ?>rem; opacity: <?= $opacity ?>;"><?= $skill ?></span>
|
<span class="tag" style="transition-delay: <?= 0.6 + ($global_i * 0.05) ?>s; font-size: <?= $fontSize ?>rem; opacity: <?= $opacity ?>;"><?= $skill ?></span>
|
||||||
<?php $global_i++; endforeach; ?>
|
<?php $global_i++;
|
||||||
</div>
|
endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
<?php endforeach; ?>
|
</div>
|
||||||
</div>
|
<?php endforeach; ?>
|
||||||
</section>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section class="cv-section experience hidden hidden-toggle">
|
<section class="cv-section experience hidden hidden-toggle">
|
||||||
<h2>Past Experience</h2>
|
<h2>Past Experience</h2>
|
||||||
@ -219,26 +219,27 @@ if ($firstJob):
|
|||||||
<?php if ($edu['desc']): ?>
|
<?php if ($edu['desc']): ?>
|
||||||
<p class="cv-desc"><?= $edu['desc'] ?></p>
|
<p class="cv-desc"><?= $edu['desc'] ?></p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<section class="cv-section skills hidden hidden-toggle">
|
<section class="cv-section skills hidden hidden-toggle">
|
||||||
<h2>Skills</h2>
|
<h2>Skills</h2>
|
||||||
<div class="skill-categories">
|
<div class="skill-categories">
|
||||||
<?php
|
<?php
|
||||||
$global_i = 0;
|
$global_i = 0;
|
||||||
foreach ($cv_skills as $category => $skills): ?>
|
foreach ($cv_skills as $category => $skills): ?>
|
||||||
<div class="skill-group">
|
<div class="skill-group">
|
||||||
<h3><?= $category ?></h3>
|
<h3><?= $category ?></h3>
|
||||||
<div class="skill-tags">
|
<div class="skill-tags">
|
||||||
<?php foreach ($skills as $skill):
|
<?php foreach ($skills as $skill):
|
||||||
$fontSize = 0.85 + (($global_i * 3) % 5) * 0.2;
|
$fontSize = 0.85 + (($global_i * 3) % 5) * 0.2;
|
||||||
$opacity = 0.6 + (($global_i * 2) % 4) * 0.1;
|
$opacity = 0.6 + (($global_i * 2) % 4) * 0.1;
|
||||||
?>
|
?>
|
||||||
<span class="tag" style="transition-delay: <?= 0.6 + ($global_i * 0.05) ?>s; font-size: <?= $fontSize ?>rem; opacity: <?= $opacity ?>;"><?= $skill ?></span>
|
<span class="tag" style="transition-delay: <?= 0.6 + ($global_i * 0.05) ?>s; font-size: <?= $fontSize ?>rem; opacity: <?= $opacity ?>;"><?= $skill ?></span>
|
||||||
<?php $global_i++; endforeach; ?>
|
<?php $global_i++;
|
||||||
</div>
|
endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
<?php endforeach; ?>
|
</div>
|
||||||
</div>
|
<?php endforeach; ?>
|
||||||
</section>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
</article>
|
</article>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
@ -248,92 +249,97 @@ if ($firstJob):
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
((u, d, t) => {
|
((u, d, t) => {
|
||||||
const addr = (atob(u) + '@' + d + '.' + t).trim();
|
const addr = (atob(u) + '@' + d + '.' + t).trim();
|
||||||
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');
|
||||||
|
|
||||||
const animationDuration = 500; // Matches CSS animation duration (0.5s)
|
const animationDuration = 500; // Matches CSS animation duration (0.5s)
|
||||||
const staggerDelay = 200; // Delay between each panel unrolling (ms)
|
const staggerDelay = 200; // Delay between each panel unrolling (ms)
|
||||||
|
|
||||||
const toggleCV = (show, updateHash = true, animate = true) => {
|
const toggleCV = (show, updateHash = true, animate = true) => {
|
||||||
const grid = document.querySelector('.bento-grid');
|
const grid = document.querySelector('.bento-grid');
|
||||||
const labelText = document.getElementById('toggle-label-text');
|
const labelText = document.getElementById('toggle-label-text');
|
||||||
|
|
||||||
if (labelText) labelText.innerText = show ? 'SYSTEM ACCESS: CV_DATA' : 'Looking to hire?';
|
if (labelText) labelText.innerText = show ? 'SYSTEM ACCESS: CV_DATA' : 'Looking to hire?';
|
||||||
|
|
||||||
const cvPanels = Array.from(document.querySelectorAll('.hidden-toggle')).filter(el => el);
|
const cvPanels = Array.from(document.querySelectorAll('.hidden-toggle')).filter(el => el);
|
||||||
|
|
||||||
if (show) {
|
if (show) {
|
||||||
grid.classList.add('cv-mode');
|
grid.classList.add('cv-mode');
|
||||||
|
|
||||||
cvPanels.forEach((el, index) => {
|
cvPanels.forEach((el, index) => {
|
||||||
const reveal = () => {
|
const reveal = () => {
|
||||||
el.classList.remove('hidden', 'fade-out', 'reveal');
|
el.classList.remove('hidden', 'fade-out', 'reveal');
|
||||||
void el.offsetWidth; // Force reflow
|
void el.offsetWidth; // Force reflow
|
||||||
el.classList.add('reveal');
|
el.classList.add('reveal');
|
||||||
};
|
};
|
||||||
if (animate) setTimeout(reveal, index * staggerDelay);
|
if (animate) setTimeout(reveal, index * staggerDelay);
|
||||||
else reveal();
|
else reveal();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const panels = [...cvPanels].reverse();
|
const panels = [...cvPanels].reverse();
|
||||||
panels.forEach((el, index) => {
|
panels.forEach((el, index) => {
|
||||||
const hide = () => {
|
const hide = () => {
|
||||||
el.classList.remove('reveal');
|
el.classList.remove('reveal');
|
||||||
if (animate) {
|
if (animate) {
|
||||||
el.classList.add('fade-out');
|
el.classList.add('fade-out');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
el.classList.add('hidden');
|
el.classList.add('hidden');
|
||||||
el.classList.remove('fade-out');
|
el.classList.remove('fade-out');
|
||||||
}, animationDuration);
|
}, animationDuration);
|
||||||
} else {
|
} else {
|
||||||
el.classList.add('hidden');
|
el.classList.add('hidden');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (animate) setTimeout(hide, index * staggerDelay);
|
if (animate) setTimeout(hide, index * staggerDelay);
|
||||||
else hide();
|
else hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (animate) {
|
if (animate) {
|
||||||
// Remove cv-mode only after the longest-running shrink animation finishes
|
// Remove cv-mode only after the longest-running shrink animation finishes
|
||||||
const totalRollupTime = (cvPanels.length * staggerDelay) + animationDuration;
|
const totalRollupTime = (cvPanels.length * staggerDelay) + animationDuration;
|
||||||
setTimeout(() => grid.classList.remove('cv-mode'), totalRollupTime);
|
setTimeout(() => grid.classList.remove('cv-mode'), totalRollupTime);
|
||||||
} else {
|
} else {
|
||||||
grid.classList.remove('cv-mode');
|
grid.classList.remove('cv-mode');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateHash) {
|
if (updateHash) {
|
||||||
window.location.hash = show ? 'CV' : '';
|
window.location.hash = show ? 'CV' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep toggle in sync
|
// Keep toggle in sync
|
||||||
const toggle = document.getElementById('cv-toggle');
|
const toggle = document.getElementById('cv-toggle');
|
||||||
if (toggle) toggle.checked = show;
|
if (toggle) toggle.checked = show;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize state from URL
|
// Initialize state from URL
|
||||||
const checkHash = (animate = false) => toggleCV(window.location.hash === '#CV', false, animate);
|
const checkHash = (animate = false) => toggleCV(window.location.hash === '#CV', false, animate);
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
checkHash(false);
|
checkHash(false);
|
||||||
// Small delay to ensure initial styles are applied before enabling transitions
|
// Small delay to ensure initial styles are applied before enabling transitions
|
||||||
setTimeout(() => document.body.classList.remove('preload'), 20);
|
setTimeout(() => document.body.classList.remove('preload'), 20);
|
||||||
});
|
});
|
||||||
window.addEventListener('hashchange', () => checkHash(true));
|
window.addEventListener('hashchange', () => checkHash(true));
|
||||||
|
|
||||||
const cvToggleInput = document.getElementById('cv-toggle');
|
const cvToggleInput = document.getElementById('cv-toggle');
|
||||||
cvToggleInput?.addEventListener('change', (e) => {
|
cvToggleInput?.addEventListener('change', (e) => {
|
||||||
toggleCV(e.target.checked);
|
toggleCV(e.target.checked);
|
||||||
|
|
||||||
// Only scroll to top if we are collapsing the CV and the user is scrolled down
|
// Only scroll to top if we are collapsing the CV and the user is scrolled down
|
||||||
if (!e.target.checked && window.scrollY > 200) {
|
if (!e.target.checked && window.scrollY > 200) {
|
||||||
window.scrollTo({ top: document.querySelector('.cv-container').offsetTop - 20, behavior: 'smooth' });
|
window.scrollTo({
|
||||||
}
|
top: document.querySelector('.cv-container').offsetTop - 20,
|
||||||
});
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<!-- Cloudflare Web Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "90827cb740cd4b1db611be059f64daa9"}'></script><!-- End Cloudflare Web Analytics -->
|
<!-- Cloudflare Web Analytics -->
|
||||||
</body>
|
<script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "90827cb740cd4b1db611be059f64daa9"}'></script><!-- End Cloudflare Web Analytics -->
|
||||||
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Loading…
Reference in New Issue
Block a user