diff --git a/routes/routes.js b/routes/routes.js index 1b391dc..56e7c63 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -1,12 +1,29 @@ import { Router } from 'express' -import routex from '../libs/routex.js' +import wrapper from '../libs/database/wrapper.js' +import tx from '../libs/routex.js' const routes = Router() routes.get( '/', (req, res) => { - routex(req, res)('pages/landing.njk', null, { currentSection: null }) + tx(req, res)('pages/landing.njk', null, { currentSection: null }) + } +) + +routes.get( + '/maps', + (req, res) => { + const maps = wrapper.allMaps() + tx(req, res)('pages/maps.njk', { maps }, { currentSection: "maps" }) + } +) + +routes.get( + '/maps/:map', + (req, res) => { + const map = wrapper.map(req.params.map) + tx(req, res)('pages/mapSingle.njk', { map }, { currentSection: "maps" }) } ) diff --git a/src/sass/maps.scss b/src/sass/maps.scss new file mode 100644 index 0000000..6960e37 --- /dev/null +++ b/src/sass/maps.scss @@ -0,0 +1,67 @@ +@use "partials/palette.scss"; +@use "partials/settings.scss"; +@use "partials/shadows.scss"; + +.maps-container { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-around; +} + +.map { + background-color: palette.$grey3; + border-radius: settings.$border_radius_m; + box-shadow: shadows.$small; + + display: flex; + flex-direction: column; + justify-content: center; + margin: 2rem 1rem; + + transition: transform .3s, box-shadow .3s; + + &:hover { + transform: scale(1.05); + box-shadow: shadows.$large; + } +} + +.map-image { + border-radius: settings.$border_radius_m settings.$border_radius_m 0 0; + width: 360px; + height: 225px; +} + +.map-name { + font-size: 1.2rem; + font-weight: bold; + + margin: .5rem 2rem; +} + +.map-info { + margin: .25rem 2rem; + + td:first-child { + width: 9ch; + } +} + +a.map-more-info { + margin: .75rem auto 1.25rem auto; + padding: .15rem .5rem; + + border: .1rem solid palette.$accent; + border-radius: settings.$border_radius_s; + + color: palette.$accent; + + text-decoration: none transparent; + transition: color .3s, background-color .3s; + + &:hover { + color: palette.$surface; + background-color: palette.$accent; + } +} \ No newline at end of file diff --git a/src/sass/partials/_shadows.scss b/src/sass/partials/_shadows.scss index 81f196c..e195eb6 100644 --- a/src/sass/partials/_shadows.scss +++ b/src/sass/partials/_shadows.scss @@ -1,4 +1,5 @@ @use "_palette.scss"; $small: .25rem 0 2rem palette.$grey1; +$medium: .35rem 0 3rem palette.$grey1; $large: .5rem 0 4rem palette.$grey1; \ No newline at end of file diff --git a/src/sass/theme.scss b/src/sass/theme.scss index 507cd2d..31b4a11 100644 --- a/src/sass/theme.scss +++ b/src/sass/theme.scss @@ -92,6 +92,10 @@ header { } } +a { + color: palette.$blue5; +} + // // FORMS, INPUT diff --git a/static/css/maps.css b/static/css/maps.css new file mode 100644 index 0000000..277fbfd --- /dev/null +++ b/static/css/maps.css @@ -0,0 +1 @@ +.maps-container{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-around}.map{background-color:#20203f;border-radius:1rem;box-shadow:.25rem 0 2rem #00001f;display:flex;flex-direction:column;justify-content:center;margin:2rem 1rem;transition:transform .3s,box-shadow .3s}.map:hover{transform:scale(1.05);box-shadow:.5rem 0 4rem #00001f}.map-image{border-radius:1rem 1rem 0 0;width:360px;height:225px}.map-name{font-size:1.2rem;font-weight:bold;margin:.5rem 2rem}.map-info{margin:.25rem 2rem}.map-info td:first-child{width:9ch}a.map-more-info{margin:.75rem auto 1.25rem auto;padding:.15rem .5rem;border:.1rem solid #fba7c6;border-radius:.5rem;color:#fba7c6;text-decoration:none transparent;transition:color .3s,background-color .3s}a.map-more-info:hover{color:#10102f;background-color:#fba7c6} diff --git a/static/css/theme.css b/static/css/theme.css index 4ffd024..c822645 100644 --- a/static/css/theme.css +++ b/static/css/theme.css @@ -1 +1 @@ -*{margin:0;padding:0;border:0 none transparent;box-sizing:border-box;scroll-behavior:smooth;font-family:"Manrope Regular",sans-serif;font-size:1rem;line-height:1.5}html,body{color:#e0e0ff;background-color:#10102f;height:100%}nav{display:flex;align-items:center;background-color:#20203f;border-radius:0 0 2rem 2rem;box-shadow:.5rem 0 4rem #00001f;margin:0 0 2rem 0;padding:1rem 2rem}nav .logo{width:3rem;height:3rem;margin-right:2rem;border-radius:100%;background-color:#ee588f}nav a{color:#fba7c6;border-bottom:.1rem solid transparent;margin:.25rem 1rem .5rem 1rem;padding:.15rem .5rem .25rem .5rem;font-size:1.25rem;text-decoration:none transparent;transition:border .3s}nav a:hover{border-bottom:.1rem solid #fba7c6}nav a.current{color:#ee588f}nav a.current:hover{border-bottom:.1rem solid #ee588f}header,h1,h2,h3,h4,h5,h6{color:#fba7c6}header{font-size:4rem}h1{font-size:1.5rem;font-weight:normal}h2{font-size:1.35rem;font-weight:normal}h3{font-size:1.2rem;font-weight:normal}h4{font-size:1.05rem;font-weight:normal}h5{font-size:.9rem;font-weight:normal}form{display:flex;flex-direction:column;justify-content:center;align-items:center}input{color:#e0e0ff;background-color:#20203f;margin:1em 0;padding:.75em 1.25em;width:min(80ch,80vw);outline:0 none transparent;border:.2rem solid transparent;border-radius:.5rem;box-shadow:.25rem 0 2rem #00001f;transition:border .3s,background-color .5s,border-radius .5s}input:hover{background-color:#30304f;border-radius:1rem}input:active,input:focus{border:.2rem solid #ee588f}footer{display:flex;flex-direction:column;align-items:center;margin:5vh 2rem}footer a{color:#74b6fb;font-size:.8rem} +*{margin:0;padding:0;border:0 none transparent;box-sizing:border-box;scroll-behavior:smooth;font-family:"Manrope Regular",sans-serif;font-size:1rem;line-height:1.5}html,body{color:#e0e0ff;background-color:#10102f;height:100%}nav{display:flex;align-items:center;background-color:#20203f;border-radius:0 0 2rem 2rem;box-shadow:.5rem 0 4rem #00001f;margin:0 0 2rem 0;padding:1rem 2rem}nav .logo{width:3rem;height:3rem;margin-right:2rem;border-radius:100%;background-color:#ee588f}nav a{color:#fba7c6;border-bottom:.1rem solid transparent;margin:.25rem 1rem .5rem 1rem;padding:.15rem .5rem .25rem .5rem;font-size:1.25rem;text-decoration:none transparent;transition:border .3s}nav a:hover{border-bottom:.1rem solid #fba7c6}nav a.current{color:#ee588f}nav a.current:hover{border-bottom:.1rem solid #ee588f}header,h1,h2,h3,h4,h5,h6{color:#fba7c6}header{font-size:4rem}h1{font-size:1.5rem;font-weight:normal}h2{font-size:1.35rem;font-weight:normal}h3{font-size:1.2rem;font-weight:normal}h4{font-size:1.05rem;font-weight:normal}h5{font-size:.9rem;font-weight:normal}a{color:#a3cefa}form{display:flex;flex-direction:column;justify-content:center;align-items:center}input{color:#e0e0ff;background-color:#20203f;margin:1em 0;padding:.75em 1.25em;width:min(80ch,80vw);outline:0 none transparent;border:.2rem solid transparent;border-radius:.5rem;box-shadow:.25rem 0 2rem #00001f;transition:border .3s,background-color .5s,border-radius .5s}input:hover{background-color:#30304f;border-radius:1rem}input:active,input:focus{border:.2rem solid #ee588f}footer{display:flex;flex-direction:column;align-items:center;margin:5vh 2rem}footer a{color:#74b6fb;font-size:.8rem} diff --git a/static/scripts/lazyLoadImages.js b/static/scripts/lazyLoadImages.js new file mode 100644 index 0000000..9da63ba --- /dev/null +++ b/static/scripts/lazyLoadImages.js @@ -0,0 +1,24 @@ +const observerConfig = { + rootMargin: '0px 0px 50px 0px', + threshold: 0 +} + +const observer = new IntersectionObserver( + (entries, self) => { + for (const entry of entries) { + if (entry.isIntersecting) { + const element = entry.target + const src = entry.target.getAttribute("data-src") + + element.setAttribute("src", src) + self.unobserve(element) + } + } + }, + observerConfig +) + + +const images = document.querySelectorAll('img[data-src]') ?? [] +for (const image of images) + observer.observe(image) \ No newline at end of file diff --git a/views/components/_map.njk b/views/components/_map.njk new file mode 100644 index 0000000..67126b3 --- /dev/null +++ b/views/components/_map.njk @@ -0,0 +1,38 @@ +{% macro card(map) %} +
+ +

{{ map.map }}

+ + + + + + + + + + + + + +
+ {% if map.mappers[1] %} + Mappers: + {% else %} + Mapper: + {% endif %} + + {{ map.mappers.join(", ") }} +
+ Category: + + {{ map.category }} +
+ Rating: + + {% for i in range(0, map.stars) %}★{% endfor %} + {% for i in range(0, 5 - map.stars) %}☆{% endfor %} +
+ More Info +
+{% endmacro %} \ No newline at end of file diff --git a/views/pages/mapSingle.njk b/views/pages/mapSingle.njk new file mode 100644 index 0000000..118a019 --- /dev/null +++ b/views/pages/mapSingle.njk @@ -0,0 +1,14 @@ +{% extends "../templates/basic.njk" %} +{% import "../components/_map.njk" as mapComponent %} + +{% block head %} + DDStats - Maps! + + +{% endblock %} + +{% block body %} +
+ {{ mapComponent.card(data.map) }} +
+{% endblock %} \ No newline at end of file diff --git a/views/pages/maps.njk b/views/pages/maps.njk new file mode 100644 index 0000000..9f9b23d --- /dev/null +++ b/views/pages/maps.njk @@ -0,0 +1,16 @@ +{% extends "../templates/basic.njk" %} +{% import "../components/_map.njk" as mapComponent %} + +{% block head %} + DDStats - Maps! + + +{% endblock %} + +{% block body %} +
+ {% for map in data.maps %} + {{ mapComponent.card(map) }} + {% endfor %} +
+{% endblock %} \ No newline at end of file