Nav menu, styling changes, start world map

This commit is contained in:
Sky Johnson 2024-10-10 13:14:14 -05:00
parent 3c0e7590ce
commit a564a96625
21 changed files with 306 additions and 72 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,9 @@
@import '/assets/css/forms.css';
:root {
font-size: 16px;
}
* {
margin: 0;
padding: 0;
@ -115,42 +119,155 @@ header {
main {
padding: 1rem;
display: grid;
grid-template-columns: 1fr 8fr 1fr;
width: 100%;
display: flex;
gap: 2rem;
#center {
flex: 1;
}
}
aside#left {
aside {
min-width: 200px;
.box {
background-color: rgba(0, 0, 0, 0.2);
border-radius: 0.15rem;
}
}
&#nav > a {
display: block;
width: 100%;
aside#left nav {
& > *:not(:last-child) {
margin-bottom: 0.25rem;
}
div.stack {
background-color: rgba(0, 0, 0, 0.2);
border-radius: 0.15rem;
input[type="checkbox"] {
display: none;
&:checked ~ div.list {
display: block;
}
&:checked + label {
background-color: rgba(0, 0, 0, 0.5);
color: white;
}
}
label {
display: flex;
align-items: center;
padding: 0.5rem 1rem;
border-radius: 0.15rem;
text-decoration: none;
color: black;
transition: color, background-color 0.2s ease;
cursor: pointer;
&:hover, &.active {
color: white;
img {
height: 18px;
margin-right: 0.25rem;
}
span.text {
display: block;
width: 100%;
}
&:hover {
color: white;
background-color: rgba(0, 0, 0, 0.3);
}
&.active {
background-color: #444c55;
color: #ffffff;
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.1));
border: 1px solid;
border-color: #3D444C #2F353B #2C3137;
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
span.arrow {
position: relative;
top: 5px;
}
}
div.list {
display: none;
& > a {
display: block;
width: 100%;
padding: 0.5rem 1rem 0.5rem 1.35rem;
border-radius: 0.15rem;
text-decoration: none;
color: black;
transition: color, background-color 0.2s ease;
&:not(:last-child)::before {
content: '├';
display: inline-block;
margin-right: 0.25rem;
}
&:last-child::before {
content: '└';
display: inline-block;
position: relative;
top: 3px;
margin-right: 0.25rem;
}
&:hover {
background-color: rgba(0, 0, 0, 0.3);
}
&.active {
background-color: #444c55;
color: #ffffff;
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.1));
border: 1px solid;
border-color: #3D444C #2F353B #2C3137;
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
}
}
}
}
& > a {
display: block;
width: 100%;
padding: 0.5rem 1rem;
text-decoration: none;
color: black;
transition: color, background-color 0.2s ease;
background-color: rgba(0, 0, 0, 0.2);
border-radius: 0.15rem;
&:has(img) {
display: flex;
align-items: center;
img {
height: 18px;
margin-right: 0.25rem;
}
}
&:hover, &.active {
color: white;
}
&:hover {
background-color: rgba(0, 0, 0, 0.3);
}
&.active {
background-color: #444c55;
color: #ffffff;
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.1));
border: 1px solid;
border-color: #3D444C #2F353B #2C3137;
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
}
}
}
@ -171,19 +288,26 @@ footer {
#char-bar {
display: flex;
align-items: center;
justify-content: space-around;
padding: 0 1rem;
height: 34px;
color: white;
gap: 1rem;
background-image: url('/assets/img/bar.jpg');
& > div {
& > div.container {
display: flex;
align-items: center;
gap: 1rem;
.icon {
width: 18px;
margin-right: 0.5rem;
& > div {
display: flex;
align-items: center;
.icon {
width: 18px;
margin-right: 0.5rem;
}
}
}
}
@ -325,6 +449,9 @@ h1:has(.badge), h2:has(.badge), h3:has(.badge), h4:has(.badge), h5:has(.badge),
transition: opacity .1s ease, color .1s ease, background .1s ease, box-shadow .1s ease;
border-radius: .28571429rem;
box-shadow: 0 0 0 1px rgba(34, 36, 38, .22) inset, 0 0 0 0 transparent;
display: flex;
align-items: center;
justify-content: space-between;
&.success {
background-color: #f0f9eb;
@ -355,6 +482,13 @@ h1:has(.badge), h2:has(.badge), h3:has(.badge), h4:has(.badge), h5:has(.badge),
color: #2c2c2c;
border-color: #b3b3b3;
}
a[alert-close] {
text-decoration: none;
cursor: pointer;
font-size: 2rem;
color: inherit;
}
}
a {
@ -367,3 +501,19 @@ a {
text-decoration: underline;
}
}
body::-webkit-scrollbar {
width: 0.5rem;
}
body::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.1);
}
body::-webkit-scrollbar-thumb {
background-color: #444c55;
background-image: linear-gradient(rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.1));
border: 1px solid;
border-color: #3D444C #2F353B #2C3137;
box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset;
}

View File

@ -52,9 +52,14 @@
}
.character-select > .radio-block {
display: inline-block;
background-color: rgba(0, 0, 0, 0.2);
border-radius: 0.15rem;
&:not(:last-child) {
margin-bottom: 0.25rem;
}
& > input[type="radio"] {
display: none;
}
@ -81,7 +86,7 @@
& > span.selected {
display: none;
margin-left: auto;
margin-left: 1rem;
color: #a6e3a1;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -13,7 +13,8 @@ $r = [];
*/
router_get($r, '/', function () {
if (user()) must_have_character();
echo render('layouts/basic', ['view' => 'pages/home', 'activeTab' => nav_tabs['home']]);
$GLOBALS['active_nav_tab'] = 'home';
echo render('layouts/basic', ['view' => 'pages/home']);
});
/*
@ -34,6 +35,15 @@ router_get($r, '/character/create-first', 'char_controller_create_first_get');
router_post($r, '/character/create', 'char_controller_create_post');
router_post($r, '/character/delete', 'char_controller_delete_post');
/*
World
*/
router_get($r, '/world', function () {
auth_only_and_must_have_character();
$GLOBALS['active_nav_tab'] = 'world';
echo page('world/base');
});
/*
Router
*/
@ -42,8 +52,10 @@ stopwatch_start('router');
$l = router_lookup($r, $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
stopwatch_stop('router');
stopwatch_start('handler');
if ($l['code'] !== 200) router_error($l['code']);
$l['handler'](...$l['params'] ?? []);
stopwatch_stop('handler');
/*
Cleanup

View File

@ -1,10 +1,5 @@
<?php
const nav_tabs = [
'home' => 0,
'chars' => 1,
];
/**
* Render the logout button's form.
*/
@ -29,13 +24,7 @@ function c_char_bar()
*/
function c_left_nav()
{
$tab = match ($GLOBALS['active_nav_tab'] ?? '') {
'home' => 0,
'chars' => 1,
default => 0
};
return render('components/left_nav', ['ant' => $tab]);
return render('components/left_nav');
}
/**
@ -57,9 +46,10 @@ function c_char_select_box($id, $char)
/**
* Render an alert with a given type and message.
*/
function c_alert($t, $m)
function c_alert($type, $message)
{
return "<div class=\"alert $t\">$m</div>";
$a = $type !== 'danger' ? ' auto-close="5000"' : '';
return "<div class=\"alert $type\"$a><div>$message</div> <a alert-close>&times;</a></div>";
}
/**
@ -71,7 +61,8 @@ function c_form_errors($placement = '')
if ($errors === false) return '';
$html = '';
foreach ($errors as $field)
foreach ($field as $message) $html .= "<p>$message</p>";
if (!empty($field))
foreach ($field as $message) $html .= !empty($message) ? "<p>$message</p>" : '';
return c_alert('danger', $html);
}

View File

@ -48,7 +48,7 @@ function char_controller_list_post()
change_user_character($char_id);
flash('alert_character_list_1', ['success', 'Switched to character <b>' . char('name') . '</b>!']);
flash('alert_character_list_1', ['success', 'Switched to <b>' . char('name') . '</b>!']);
}
// If the action is to delete a character, move to the confirmation page.

View File

@ -223,3 +223,11 @@ function stopwatch_get($key)
if (empty($GLOBALS['stopwatch'][$key])) return 0;
return number_format($GLOBALS['stopwatch'][$key], 10);
}
/**
* Conditional Echo; if the condition is true, echo the value. If the condition is false, echo the $or value.
*/
function ce($condition, $value, $or = '')
{
echo $condition ? $value : $or;
}

View File

@ -1,34 +1,36 @@
<div id="char-bar">
<div>
<img class="icon" src="/assets/img/icons/user1.png" alt="User">
<?= $char['name'] ?> <span class="badge ml-2 tooltip-hover" data-tooltip-content="Level"><?= $char['level'] ?></span>
<?php if ($char['attrib_points'] > 0): ?>
<span class="ui button primary badge ml-2 tooltip-hover" data-tooltip-content="Attribute Points"><?= $char['attrib_points'] ?></span>
<?php endif; ?>
</div>
<div>
<div class="char-meter">
<div class="hp" style="width: <?= percent($char['current_hp'], $char['max_hp']) ?>%"></div>
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Health<br><?= $char['current_hp'] ?> / <?= $char['max_hp'] ?>"></div>
<div class="container">
<div>
<img class="icon" src="/assets/img/icons/user1.png" alt="User">
<?= $char['name'] ?> <span class="badge ml-2 tooltip-hover" data-tooltip-content="Level"><?= $char['level'] ?></span>
<?php if ($char['attrib_points'] > 0): ?>
<span class="ui button primary badge ml-2 tooltip-hover" data-tooltip-content="Attribute Points"><?= $char['attrib_points'] ?></span>
<?php endif; ?>
</div>
</div>
<div>
<div class="char-meter">
<div class="mp" style="width: <?= percent($char['current_mp'], $char['max_mp']) ?>%"></div>
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Mana<br><?= $char['current_mp'] ?> / <?= $char['max_mp'] ?>"></div>
<div>
<div class="char-meter">
<div class="hp" style="width: <?= percent($char['current_hp'], $char['max_hp']) ?>%"></div>
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Health<br><?= $char['current_hp'] ?> / <?= $char['max_hp'] ?>"></div>
</div>
</div>
</div>
<div>
<div class="char-meter">
<div class="tp" style="width: <?= percent($char['current_tp'], $char['max_tp']) ?>%"></div>
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Travel Points<br><?= $char['current_tp'] ?> / <?= $char['max_tp'] ?>"></div>
<div>
<div class="char-meter">
<div class="mp" style="width: <?= percent($char['current_mp'], $char['max_mp']) ?>%"></div>
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Mana<br><?= $char['current_mp'] ?> / <?= $char['max_mp'] ?>"></div>
</div>
</div>
</div>
<div>
<?= wallet('silver') ?> Silver
<div>
<div class="char-meter">
<div class="tp" style="width: <?= percent($char['current_tp'], $char['max_tp']) ?>%"></div>
<div class="tooltip-trigger tooltip-hover" data-tooltip-content="Travel Points<br><?= $char['current_tp'] ?> / <?= $char['max_tp'] ?>"></div>
</div>
</div>
<div>
<?= wallet('silver') ?> Silver
</div>
</div>
</div>

View File

@ -3,6 +3,6 @@
<label for="char_<?= $id ?>">
<?= $char['name'] ?>
<span class="badge"><?= $char['level'] ?></span>
<span class="selected">Currently Playing</span>
<span class="selected">Active</span>
</label>
</div>

View File

@ -3,4 +3,5 @@
<p class="mb-2">Page execution took <?= number_format((microtime(true) - START_TIME), 10) ?> seconds.</p>
<p>Bootstrap: <?= stopwatch_get('bootstrap') ?> seconds</p>
<p>Router: <?= stopwatch_get('router') ?> seconds</p>
<p>Handler: <?= stopwatch_get('handler') ?> seconds</p>
</div>

View File

@ -1,4 +1,18 @@
<div id="nav" class="box">
<a href="/" class="<?= $ant === 0 ? 'active' : '' ?>">Home</a>
<a href="/characters" class="<?= $ant === 1 ? 'active' : '' ?>">Characters</a>
</div>
<nav>
<?php
const links = [
['/', 'home', 'home', 'Home'],
['/world', 'world', 'earth', 'World'],
['/profile', 'profile', 'user1', 'Profile'],
['/auctions', 'auctions', 'shop', 'Auctions'],
['/characters', 'chars', 'user1', 'Characters'],
['/settings', 'settings', 'settings', 'Settings']
];
foreach (links as $link): ?>
<a href="<?= $link[0] ?>" class="<?= ce(($GLOBALS['active_nav_tab'] ?? '') == $link[1], 'active') ?>">
<img src="/assets/img/icons/<?= $link[2] ?>.png">
<?= $link[3] ?>
</a>
<?php endforeach; ?>
</nav>

View File

@ -0,0 +1,34 @@
<canvas></canvas>
<script>
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;
const tile_height = 32;
const tile_width = 32;
const map = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
// render the map
map.forEach((tile, index) => {
const x = (index % 10) * tile_width;
const y = Math.floor(index / 10) * tile_height;
ctx.fillStyle = tile === 0 ? 'black' : 'white';
ctx.fillRect(x, y, tile_width, tile_height);
});
</script>

View File

@ -27,9 +27,7 @@
<main>
<aside id="left">
<?php if (user()): ?>
<?= c_left_nav($activeTab ?? 0) ?>
<?php endif; ?>
<?php if (user()) echo c_left_nav($activeTab ?? 0); ?>
</aside>
<div id="center">
@ -46,8 +44,8 @@
<footer>
<p>&copy; <?= date('Y') ?> Dragon Knight</p>
<p>q<?= $GLOBALS['queries'] ?></p>
<p>qt<?= number_format($GLOBALS['query_time'], env('debug', false) === true ? 6 : 2) ?></p>
<p>t<?= number_format((microtime(true) - START_TIME), env('debug', false) === true ? 6 : 2) ?></p>
<p>qt<?= number_format($GLOBALS['query_time'], 3) ?></p>
<p>t<?= number_format((microtime(true) - START_TIME), 3) ?></p>
<p>v<?= env('version') ?></p>
</footer>
@ -61,5 +59,21 @@
import Tooltip from '/assets/scripts/tooltip.js';
Tooltip.init();
</script>
<script>
// Get all elements with data-alert-close attribute; when clicked, delete parent element
document.querySelectorAll('[alert-close]').forEach(function (el) {
el.addEventListener('click', function () {
el.parentNode.remove();
});
});
// Get all elements with a data-auto-close attribute; after x seconds, delete the element
document.querySelectorAll('[auto-close]').forEach(function (el) {
setTimeout(function () {
el.remove();
}, el.getAttribute('auto-close'));
});
</script>
</body>
</html>

View File

@ -0,0 +1,3 @@
<h1>World</h1>
<?= render('components/world_map') ?>