Major rewrite for 0.1.6 - Dynamic database entry generation based on json files, dynamic run page generation and more
This commit is contained in:
parent
e75a575417
commit
7fe9e8c25f
28 changed files with 2954 additions and 45 deletions
src
assets
components
content/data
layouts
pages
types
utils
BIN
src/assets/embed.png
Normal file
BIN
src/assets/embed.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 7 KiB |
58
src/assets/logo.svg
Normal file
58
src/assets/logo.svg
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="110.08278mm"
|
||||
height="101.0897mm"
|
||||
viewBox="0 0 110.08278 101.0897"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
xml:space="preserve"
|
||||
inkscape:export-filename="colored_logo.svg"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="logo_2.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.76880612"
|
||||
inkscape:cx="165.84155"
|
||||
inkscape:cy="226.32494"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g429" /><defs
|
||||
id="defs2" /><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(160.03878,-49.932608)"><g
|
||||
id="g429"
|
||||
transform="translate(-210.61878,-24.090382)"
|
||||
inkscape:export-filename="g429.svg"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:groupmode="layer"><path
|
||||
style="fill:#ffffff;stroke-width:0.107"
|
||||
d="m 87.179998,136.57997 v 23.84826 l 13.810092,-13.81009 v -9.79482 h 16.73028 l 12.50209,-12.50209 h -29.23237 v -9.94692 h 35.71155 l 12.16748,-12.16747 H 87.179998 v 22.14481 H 67.955379 Z"
|
||||
id="path302" /><path
|
||||
style="fill:#b86cff;fill-opacity:1;stroke-width:0.107"
|
||||
d="m 74.013398,131.76579 2.989789,1.97885 c 0,0 -24.434533,22.32662 -12.819526,37.81329 l 1.419613,-5.97957 c 0,0 15.830822,6.4958 44.094006,-10.36747 0,0 -0.6883,-12.26028 10.88369,-6.71089 0,0 13.20669,-8.08749 25.25188,-21.76738 -0.25811,-0.34415 -3.52752,-5.42034 -3.52752,-5.42034 l 0.086,-3.78563 5.3343,7.05504 c 0,0 23.23001,-28.048086 -8.77579,-24.09038 l -3.26936,-1.290557 c 0,0 39.2329,-8.861819 13.59385,27.703937 0,0 17.12138,25.89716 9.37805,39.6631 -7.74334,13.76593 -36.13558,-6.88297 -36.47973,-8.25956 -0.34414,-1.3766 24.95076,16.51912 33.72654,5.85052 8.77578,-10.6686 -9.80823,-37.51217 -8.60371,-35.10313 0,0 -13.07764,14.79838 -25.2949,22.02549 0,0 1.54867,10.75464 -10.06634,6.79693 0,0 -43.104576,26.15527 -59.19351,14.02405 0,0 -12.174247,-12.04519 21.272668,-40.1363 z"
|
||||
id="path358" /><path
|
||||
style="fill:#b86cff;fill-opacity:1;stroke-width:0.107"
|
||||
d="m 84.058227,118.30098 0.08604,-9.37804 c 0,0 -5.420336,-10.410486 -1.892816,-20.56286 -0.94641,-0.344147 -6.280709,0.602261 -6.280709,0.602261 0,0 15.400637,-16.51912 45.083428,10.152375 0.43019,0.172074 5.59241,0.08604 5.59241,0.08604 0,0 -28.134123,-30.543163 -48.524911,-24.348493 0,0 -17.293454,5.850508 5.936558,43.448717 z"
|
||||
id="path360" /></g></g></svg>
|
After (image error) Size: 3.2 KiB |
BIN
src/assets/ta_servants/shishou.png
Normal file
BIN
src/assets/ta_servants/shishou.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 31 KiB |
|
@ -1,4 +1,7 @@
|
|||
---
|
||||
import packagejson from '../../package.json'
|
||||
const version = packagejson.version
|
||||
const release = `https://forgejo.neshweb.net/Firq/fgo-ta-com-website/releases/tag/${version}`
|
||||
---
|
||||
|
||||
<div>
|
||||
|
@ -9,6 +12,8 @@
|
|||
game in general.
|
||||
<br />
|
||||
<a href="https://firq.dev" target="_blank" rel="noopener noreferrer">Feel free to check out my own site.</a>
|
||||
<br />
|
||||
<span class="version">(Website version: <a href={release} target="_blank" rel="noopener noreferrer">{version}</a>)</span>
|
||||
</span>
|
||||
<slot />
|
||||
</div>
|
||||
|
@ -30,5 +35,10 @@
|
|||
a {
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: var(--c-darkpurple);
|
||||
}
|
||||
|
||||
.version {
|
||||
font-size: 0.7em;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
---
|
||||
import { Image } from 'astro:assets';
|
||||
import logo from '../assets/logo.svg'
|
||||
import hamburger from 'iconoir/icons/menu.svg'
|
||||
const hamburger_src_url = `url("${hamburger.src}")`;
|
||||
---
|
||||
|
||||
<header>
|
||||
<a href="/" rel="noopener noreferrer" aria-label="Home">
|
||||
<img src="/assets/logo.svg" alt="" />
|
||||
<Image src={logo} alt="Website Logo"/>
|
||||
</a>
|
||||
<ul class="desktop">
|
||||
<slot />
|
||||
|
@ -13,11 +17,11 @@
|
|||
<slot />
|
||||
</ul>
|
||||
<div class="placeholder"></div>
|
||||
<i class="iconoir-menu"></i>
|
||||
<div class="hamburger-menu"></div>
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
<style define:vars={{ hamburger_src_url }}>
|
||||
header {
|
||||
z-index: 1000;
|
||||
position: sticky;
|
||||
|
@ -79,16 +83,6 @@
|
|||
height: 64px;
|
||||
}
|
||||
|
||||
.mobile > i {
|
||||
position: static;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 2em;
|
||||
align-self: flex-start;
|
||||
padding-right: 1em;
|
||||
padding-top: 1.15rem;
|
||||
}
|
||||
|
||||
.mobile > ul {
|
||||
display: none;
|
||||
padding: 0px;
|
||||
|
@ -111,6 +105,17 @@
|
|||
justify-self: top;
|
||||
}
|
||||
|
||||
.hamburger-menu {
|
||||
mask: var(--hamburger_src_url) no-repeat center;
|
||||
background-color: white;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
position: static;
|
||||
align-self: flex-start;
|
||||
padding-right: 1em;
|
||||
padding-top: 2.5em;
|
||||
}
|
||||
|
||||
@media (min-width: 1140px) {
|
||||
.mobile {
|
||||
display: none;
|
||||
|
|
|
@ -3,7 +3,7 @@ export interface Props {
|
|||
currentPage?: string
|
||||
link: string
|
||||
text: string
|
||||
icon: string
|
||||
icon: ImageMetadata
|
||||
}
|
||||
|
||||
const { icon, text, link, currentPage } = Astro.props
|
||||
|
@ -17,6 +17,7 @@ if (currentPage === slug) {
|
|||
currPage = 'current'
|
||||
}
|
||||
|
||||
const icon_src_url = `url("${icon.src}")`;
|
||||
const fulllink = `/${slug}`
|
||||
---
|
||||
|
||||
|
@ -28,12 +29,12 @@ const fulllink = `/${slug}`
|
|||
class={currPage}
|
||||
tabindex="0"
|
||||
>
|
||||
<i class={icon}></i>
|
||||
<div class="icon"></div>
|
||||
{text}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<style>
|
||||
<style define:vars={{ icon_src_url }}>
|
||||
li {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -41,7 +42,9 @@ const fulllink = `/${slug}`
|
|||
display: flex;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
li > a {
|
||||
display: inline-flex;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
justify-content: center;
|
||||
|
@ -49,11 +52,29 @@ const fulllink = `/${slug}`
|
|||
font-size: 1.4em;
|
||||
height: 100%;
|
||||
font-weight: bold;
|
||||
gap: 0.2em;
|
||||
}
|
||||
|
||||
li > a:hover {
|
||||
color: var(--c-purplepink);
|
||||
}
|
||||
|
||||
li > a:hover > .icon {
|
||||
background-color: var(--c-purplepink);
|
||||
}
|
||||
|
||||
.current {
|
||||
color: var(--c-darkpurple);
|
||||
color: var(--c-darkpurple) !important;
|
||||
}
|
||||
|
||||
.current > .icon {
|
||||
background-color: var(--c-darkpurple) !important;
|
||||
}
|
||||
|
||||
.icon {
|
||||
mask: var(--icon_src_url) no-repeat center;
|
||||
background-color: white;
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
}
|
||||
</style>
|
||||
|
|
103
src/components/questListing.astro
Normal file
103
src/components/questListing.astro
Normal file
|
@ -0,0 +1,103 @@
|
|||
---
|
||||
export interface Props {
|
||||
url: string | undefined
|
||||
title: string
|
||||
questReleaseDate: string
|
||||
shortdescription: string
|
||||
}
|
||||
|
||||
const options_date: Intl.DateTimeFormatOptions = {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
}
|
||||
const { shortdescription, questReleaseDate, url, title } = Astro.props
|
||||
const render_date = new Date(questReleaseDate).toLocaleDateString('en-GB', options_date)
|
||||
---
|
||||
|
||||
<a href={url} rel="noopener noreferrer">
|
||||
<div class="circle"></div>
|
||||
<article>
|
||||
<h2>{title}</h2>
|
||||
<h3>{render_date}</h3>
|
||||
<p>{shortdescription}</p>
|
||||
</article>
|
||||
</a>
|
||||
|
||||
<style>
|
||||
.circle {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
.circle {
|
||||
margin: 1rem 1rem 1rem 0rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
visibility: visible;
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
border-radius: 40%;
|
||||
background-color: var(--c-darkpurple);
|
||||
transition: transform var(--speed) var(--ease);
|
||||
}
|
||||
|
||||
a:hover > .circle {
|
||||
height: 1.75rem;
|
||||
width: 1.75rem;
|
||||
translate: -0.125rem;
|
||||
margin-right: 0.825rem;
|
||||
}
|
||||
|
||||
article {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
text-decoration: none;
|
||||
height: auto;
|
||||
margin: 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
p {
|
||||
color: white;
|
||||
text-align: left;
|
||||
font-size: 1.1em;
|
||||
margin: 0.5em;
|
||||
}
|
||||
article > h2 {
|
||||
margin: 0.3rem 0.5rem;
|
||||
color: var(--c-darkpurple);
|
||||
font-size: 1.5rem;
|
||||
line-height: normal;
|
||||
text-decoration: none;
|
||||
}
|
||||
article > h3 {
|
||||
margin: 0.2em 0.5rem;
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
line-height: normal;
|
||||
text-decoration: none;
|
||||
}
|
||||
article {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
justify-content: center;
|
||||
background-color: var(--c-darkergray);
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
transition: transform var(--speed) var(--ease);
|
||||
min-height: 100%;
|
||||
border-radius: 1.25rem;
|
||||
}
|
||||
a:hover > article {
|
||||
transform: scaleY(102.5%) scaleX(101%);
|
||||
}
|
||||
</style>
|
184
src/components/taCard.astro
Normal file
184
src/components/taCard.astro
Normal file
|
@ -0,0 +1,184 @@
|
|||
---
|
||||
import type { ImageMetadata } from 'astro'
|
||||
import { Image } from 'astro:assets'
|
||||
export interface Props {
|
||||
title: string,
|
||||
link: string,
|
||||
date: string,
|
||||
servant: string,
|
||||
turns: string,
|
||||
runner: string
|
||||
}
|
||||
|
||||
const { turns, runner, date, servant, link, title } =
|
||||
Astro.props
|
||||
|
||||
const options_date: Intl.DateTimeFormatOptions = {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
}
|
||||
|
||||
const servantImagePath = `/src/assets/ta_servants/${servant}.png`
|
||||
|
||||
const formatted_date = new Date(date).toLocaleDateString('de-DE', options_date)
|
||||
const servant_images = import.meta.glob<{ default: ImageMetadata }>(
|
||||
'/src/assets/ta_servants/*.png'
|
||||
)
|
||||
|
||||
---
|
||||
|
||||
<a href={link} target="_blank" rel="noopener noreferrer" aria-label={title}>
|
||||
<article>
|
||||
<Image src={servant_images[servantImagePath]()} alt="" class="icon"/>
|
||||
<div class="title">
|
||||
<h2>{title}</h2>
|
||||
</div>
|
||||
<p>
|
||||
<span>
|
||||
By {runner}<br /> •
|
||||
</span>
|
||||
{formatted_date}
|
||||
</p>
|
||||
<div class="expand-on-hover">
|
||||
<h2>{turns}</h2>
|
||||
</div>
|
||||
</article>
|
||||
</a>
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
article {
|
||||
background-color: var(--c-darkergray);
|
||||
border-color: var(--c-darkgray);
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
transition: transform var(--speed) var(--ease);
|
||||
height: auto;
|
||||
width: auto;
|
||||
max-width: 8rem;
|
||||
border-radius: 1.25rem;
|
||||
padding-bottom: 1.5rem;
|
||||
--size-value: 7rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
article:hover {
|
||||
transform: scale(var(--hover-scale));
|
||||
}
|
||||
|
||||
article > .icon {
|
||||
border-radius: 1.25rem;
|
||||
width: var(--size-value);
|
||||
height: var(--size-value);
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
||||
article:hover .title {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
background-color: var(--c-darkgray);
|
||||
height: calc(var(--size-value) + 0.1rem);
|
||||
width: calc(var(--size-value) + 0.1rem);
|
||||
opacity: 90%;
|
||||
border-radius: 1.25rem;
|
||||
top: 1.1em;
|
||||
}
|
||||
|
||||
article:hover .title h2 {
|
||||
margin: 0;
|
||||
display: inline-flex;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
line-height: 150%;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
article .title h2 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
article .title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
p {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
line-height: 100%;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
padding-top: 0.5rem;
|
||||
margin: 0.5rem 0px;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.expand-on-hover {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
background-color: var(--c-duskgray);
|
||||
z-index: 99;
|
||||
transform: scaleY(0);
|
||||
transform-origin: top;
|
||||
position: absolute;
|
||||
top: 90%;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
color: white;
|
||||
border-radius: 0px 0px 1.25rem 1.25rem;
|
||||
}
|
||||
|
||||
.expand-on-hover img {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.expand-on-hover h2 {
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
||||
article:hover .expand-on-hover {
|
||||
transform: scaleY(1);
|
||||
transition: transform 200ms ease-in-out;
|
||||
background-color: var(--c-duskgray);
|
||||
}
|
||||
</style>
|
26
src/content/data/cernunnos.json
Normal file
26
src/content/data/cernunnos.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"info": {
|
||||
"title": "Cernunnos",
|
||||
"questReleaseDate": "2023-07-10",
|
||||
"shortdescription": "One of FGOs most notorious boss fights due to up to 100% special defense, strong DoT damage and powerful field effects",
|
||||
"description": "One of FGOs most notorious boss fights due to up to 100% special defense, strong DoT damage and powerful field effects - and still, the TA community prevailed and created some of the most amazing runs of all time"
|
||||
},
|
||||
"data": [
|
||||
{
|
||||
"title": "Cernunnos 4T (No Castoria)",
|
||||
"link": "https://www.youtube.com/watch?v=WrHudtdfivA",
|
||||
"date": "2023-07-19",
|
||||
"servant": "shishou",
|
||||
"turns": "4T",
|
||||
"runner": "Firq"
|
||||
},
|
||||
{
|
||||
"title": "Cernunnos 4T (FLO)",
|
||||
"link": "https://www.youtube.com/watch?O1f-go7uJQM",
|
||||
"date": "2023-07-19",
|
||||
"servant": "shishou",
|
||||
"turns": "4T",
|
||||
"runner": "Requiem"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
---
|
||||
import Navbar from '../components/navbar.astro'
|
||||
import NavbarEntry from '../components/navbarEntry.astro'
|
||||
import navdata from '../../static/assets/data/_navdata.json'
|
||||
import navdata from '../../static/data/_navdata.json'
|
||||
import embed from '../assets/embed.png'
|
||||
import home from 'iconoir/icons/home.svg'
|
||||
import database from 'iconoir/icons/database.svg'
|
||||
import type { IconsLookup } from '../types/icons'
|
||||
|
||||
export interface Props {
|
||||
title: string
|
||||
|
@ -9,6 +13,11 @@ export interface Props {
|
|||
descriptionOverride?: string
|
||||
}
|
||||
|
||||
const icons: IconsLookup = {
|
||||
home: home,
|
||||
database: database
|
||||
}
|
||||
|
||||
const { descriptionOverride, currentpage, title } = Astro.props
|
||||
let description
|
||||
|
||||
|
@ -22,6 +31,11 @@ let currPage = 'https://fgo-ta.com/'
|
|||
if (currentpage !== 'home') {
|
||||
currPage += currentpage
|
||||
}
|
||||
|
||||
const mapped_navdata = navdata.map((item) => ({
|
||||
...item,
|
||||
...{ icon: icons[item.icon] },
|
||||
}))
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
@ -36,23 +50,19 @@ if (currentpage !== 'home') {
|
|||
<meta property="og:title" content={title} />
|
||||
<meta property="og:url" content={currPage} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image" content="/assets/embed.png" />
|
||||
<meta property="og:image" content={embed.src} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta name="theme-color" content="#b86cff" />
|
||||
<!-- Links -->
|
||||
<link rel="icon" type="image/ico" href="/assets/favicon.ico" />
|
||||
<link rel="icon" type="image/ico" href="/favicon.ico" />
|
||||
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||
<link href="https://mastodon.neshweb.net/@Firq" rel="me" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/gh/iconoir-icons/iconoir@main/css/iconoir.css"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<Navbar>
|
||||
{
|
||||
navdata.map((item) => (
|
||||
mapped_navdata.map((item) => (
|
||||
<NavbarEntry currentPage={currentpage} {...item} />
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
---
|
||||
export interface Props {
|
||||
title: string
|
||||
description: string
|
||||
}
|
||||
|
||||
const { title } = Astro.props
|
||||
const { title, description } = Astro.props
|
||||
---
|
||||
|
||||
<div class="base">
|
||||
<h1>{title}</h1>
|
||||
<h2>{description}</h2>
|
||||
<div>
|
||||
<slot />
|
||||
</div>
|
||||
|
@ -45,6 +47,16 @@ const { title } = Astro.props
|
|||
background-color: var(--c-darkgray);
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
div h2 {
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
max-width: 75;
|
||||
margin: 1rem;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
@media (min-width: 512px) {
|
||||
div {
|
||||
row-gap: 1.5em;
|
||||
|
@ -64,10 +76,18 @@ const { title } = Astro.props
|
|||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1500px) {
|
||||
@media (min-width: 1140px) {
|
||||
.base {
|
||||
margin-left: 10%;
|
||||
margin-right: 10%;
|
||||
}
|
||||
div h1 {
|
||||
margin-left: unset;
|
||||
margin-right: unset;
|
||||
}
|
||||
|
||||
div h2 {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
100
src/layouts/databaseSection.astro
Normal file
100
src/layouts/databaseSection.astro
Normal file
|
@ -0,0 +1,100 @@
|
|||
---
|
||||
export interface Props {
|
||||
title: string
|
||||
}
|
||||
|
||||
const { title } = Astro.props
|
||||
---
|
||||
|
||||
<section>
|
||||
<h1>{title}</h1>
|
||||
<div class="wrapper">
|
||||
<div class="line"></div>
|
||||
<slot />
|
||||
<div class="drop"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.drop {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
visibility: visible;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: -5rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
border-radius: 0% 50% 50% 50%;
|
||||
transform: rotate(45deg);
|
||||
background-color: var(--c-darkpurple);
|
||||
}
|
||||
.line {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
visibility: visible;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: var(--c-darkpurple);
|
||||
height: calc(100% + 5rem);
|
||||
translate: 0% 2rem;
|
||||
width: 0.25rem;
|
||||
z-index: -1;
|
||||
}
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
line-height: 48px;
|
||||
letter-spacing: -1px;
|
||||
color: white;
|
||||
font-size: 2.25rem;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 0.25rem 0.75rem;
|
||||
max-width: max-content;
|
||||
background-color: var(--c-darkgray);
|
||||
padding: 0.25rem 1.5rem;
|
||||
border-radius: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
.wrapper {
|
||||
margin: 2rem 3rem 0.5rem 3rem;
|
||||
display: flex;
|
||||
flex-flow: column wrap;
|
||||
row-gap: 1em;
|
||||
column-gap: 1em;
|
||||
align-self: center;
|
||||
align-items: stretch;
|
||||
justify-content: space-around;
|
||||
padding: 1em;
|
||||
color: white;
|
||||
font-size: 1em;
|
||||
position: relative;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
.drop {
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
.line {
|
||||
margin-left: 2.1rem;
|
||||
}
|
||||
h1 {
|
||||
margin-left: 3rem;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
.wrapper {
|
||||
margin-left: 20rem;
|
||||
margin-right: 20rem;
|
||||
}
|
||||
h1 {
|
||||
margin-left: 20rem;
|
||||
margin-right: 20rem;
|
||||
}
|
||||
}
|
||||
</style>
|
52
src/layouts/taShowcaseLayout.astro
Normal file
52
src/layouts/taShowcaseLayout.astro
Normal file
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro'
|
||||
import BaseSection from '../layouts/baseSection.astro'
|
||||
import TACard from '../components/taCard.astro'
|
||||
import type { filedata } from '../types/ta'
|
||||
|
||||
export interface Props {
|
||||
datafile: string
|
||||
}
|
||||
|
||||
const { datafile } = Astro.props
|
||||
const fulldata = import.meta.glob<{ default: any }>(
|
||||
`../content/data/*.json`
|
||||
)
|
||||
const filecontent: filedata = (
|
||||
await fulldata[`../content/data/${datafile}.json`]()
|
||||
)['default']
|
||||
|
||||
const title = filecontent.info.title
|
||||
---
|
||||
|
||||
<Layout
|
||||
title={title}
|
||||
currentpage="database-entry"
|
||||
descriptionOverride={filecontent.info.shortdescription}
|
||||
>
|
||||
<a href="/database"><< Back to database</a>
|
||||
<BaseSection title={title} description={filecontent.info.description}>
|
||||
{filecontent.data.map((item) => <TACard {...item} />)}
|
||||
</BaseSection>
|
||||
<div class="placeholder"></div>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
.placeholder {
|
||||
visibility: hidden;
|
||||
width: 100%;
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: white;
|
||||
background-color: var(--c-gray);
|
||||
padding: 0.5rem 0px;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
37
src/pages/database.astro
Normal file
37
src/pages/database.astro
Normal file
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro'
|
||||
import QuestListing from '../components/questListing.astro'
|
||||
import DatabaseSection from '../layouts/databaseSection.astro'
|
||||
import { findSlug } from '../utils/slugTools'
|
||||
import type { filedata } from '../types/ta'
|
||||
|
||||
const description =
|
||||
'My own small blog. Topics include FGO, TA, Programming, web technologies and more!'
|
||||
|
||||
const questInfo = []
|
||||
const fulldata = import.meta.glob<{ default: filedata }>(`../content/data/*.json`)
|
||||
|
||||
for (const [key, value] of Object.entries(fulldata)) {
|
||||
const url = `${Astro.url}/${findSlug(key)}`
|
||||
questInfo.push({
|
||||
...(await value())['default'].info,
|
||||
url: url,
|
||||
})
|
||||
}
|
||||
|
||||
questInfo.sort(
|
||||
(a, b) => Date.parse(b.questReleaseDate) - Date.parse(a.questReleaseDate)
|
||||
)
|
||||
---
|
||||
|
||||
<Layout
|
||||
title="TA Database"
|
||||
currentpage="database"
|
||||
descriptionOverride={description}
|
||||
>
|
||||
<DatabaseSection title="FGO NA TA Database">
|
||||
{questInfo.map((quest) => <QuestListing {...quest} />)}
|
||||
</DatabaseSection>
|
||||
</Layout>
|
||||
|
||||
<style></style>
|
23
src/pages/database/[slug].astro
Normal file
23
src/pages/database/[slug].astro
Normal file
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
import TaShowcaseLayout from '../../layouts/taShowcaseLayout.astro'
|
||||
import {findSlug} from '../../utils/slugTools'
|
||||
|
||||
export function getStaticPaths() {
|
||||
const fulldata = import.meta.glob<{ default: any }>(
|
||||
`../../content/data/*.json`
|
||||
)
|
||||
const keylist = Object.keys(fulldata).map(
|
||||
(item) => findSlug(item)
|
||||
)
|
||||
|
||||
const paths: { params: { slug: string } }[] = []
|
||||
for (const key of keylist) {
|
||||
paths.push({ params: { slug: key! } })
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
const { slug } = Astro.params
|
||||
---
|
||||
|
||||
<TaShowcaseLayout datafile={slug} />
|
3
src/types/icons.ts
Normal file
3
src/types/icons.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export interface IconsLookup {
|
||||
[key: string]: ImageMetadata
|
||||
}
|
20
src/types/ta.ts
Normal file
20
src/types/ta.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
interface tadata {
|
||||
title: string
|
||||
link: string
|
||||
servant: string
|
||||
turns: string
|
||||
runner: string
|
||||
date: string
|
||||
}
|
||||
|
||||
interface info {
|
||||
title: string
|
||||
questReleaseDate: string
|
||||
description: string
|
||||
shortdescription: string
|
||||
}
|
||||
|
||||
export interface filedata {
|
||||
info: info
|
||||
data: tadata[]
|
||||
}
|
3
src/utils/slugTools.ts
Normal file
3
src/utils/slugTools.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function findSlug(filepath: string) {
|
||||
return filepath.match(/(?:.*[\\/])(.+)(?:\.json)/)?.[1]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue