feat: add formatted_date.svelte/footer

This commit is contained in:
Keisuke Hirata 2024-08-17 21:11:27 +09:00
parent 2d1dee1f7b
commit 8e43dc76b4
4 changed files with 407 additions and 293 deletions

View File

@ -0,0 +1,90 @@
<script lang="ts">
// let location = window.location.pathname;
let links = [
{ name: 'Home', url: '/' },
{ name: 'Search', url: '/search' },
{ name: 'About Me', url: 'https://me.hareworks.net/' },
];
</script>
<footer>
<div class="banner">
<a href="https://me.hareworks.net/" target="_blank">
<img src="/img/logo.png" alt="HareWorks" width="100px" height="100px" />
</a>
<div class="copyright">
<p>© 2024 Hare</p>
</div>
</div>
<div class="separator"></div>
<div class="panel">
<ul>
{#each links as link}
<li><a href={link.url}>{link.name}</a></li>
{/each}
<li><p>Contact: hello at hareworks dot net</p></li>
</ul>
</div>
</footer>
<style lang="scss">
footer {
width: 100%;
background-color: var(--background-primary);
display: flex;
justify-content: center;
align-items: stretch;
flex-direction: row;
padding: 10px 10px;
box-sizing: border-box;
color: white;
}
.banner {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
a {
width: 100px;
height: 100px;
margin: 20px;
}
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.separator {
width: 1px;
margin: 0 20px;
background-color: var(--line-primary);
}
.panel {
width: 300px;
margin: 20px 0;
display: flex;
justify-content: space-between;
align-items: top;
flex-direction: row;
gap: 20px;
}
ul {
margin: 0;
}
li {
list-style: none;
> a,
> p {
color: lightgrey;
text-decoration: none;
padding: 2px;
margin: 0;
display: block;
text-wrap: nowrap;
}
> p {
padding-top: 15px;
}
}
</style>

View File

@ -0,0 +1,24 @@
<script lang="ts">
export let date: string | Date;
if (typeof date === 'string') date = new Date(date);
const pad = function (str: string): string {
return ('0' + str).slice(-2);
};
const year = date.getFullYear().toString();
const month = pad((date.getMonth() + 1).toString());
const day = pad(date.getDate().toString());
const hour = pad(date.getHours().toString());
const min = pad(date.getMinutes().toString());
const sec = pad(date.getSeconds().toString());
const tz = -date.getTimezoneOffset();
const sign = tz >= 0 ? '+' : '-';
const tzHour = pad((tz / 60).toString());
const tzMin = pad((tz % 60).toString());
let formattedDate = `${year}-${month}-${day}T${hour}:${min}:${sec}${sign}${tzHour}:${tzMin}`;
</script>
{formattedDate}

View File

@ -1,5 +1,5 @@
<script> <script>
import '../app.scss'; import '../app.scss';
</script> </script>
<slot /> <slot />

View File

@ -1,307 +1,307 @@
<script lang="ts"> <script lang="ts">
import type { PageData } from './$types'; import type { PageData } from './$types';
// import Cursor from '$lib/components/cursor.svelte'; // import Cursor from '$lib/components/cursor.svelte';
// import Footer from '$lib/components/footer.svelte'; import Footer from '$lib/components/footer.svelte';
import FormattedDate from '$lib/components/formatted_date.svelte';
export let data: PageData; export let data: PageData;
let refresh = true; let refresh = true;
let searchInput: HTMLInputElement; let searchInput: HTMLInputElement;
let suggest: HTMLDivElement; let suggest: HTMLDivElement;
const emojis = ['( ᐢ˙꒳˙ᐢ )', '(=`•ω•´)', '₍ᐢ。•༝•。ᐢ₎', 'ヽ(・ω・*)', '( |||| ᐢ˙꒳˙ᐢ )']; const emojis = ['( ᐢ˙꒳˙ᐢ )', '(=`•ω•´)', '₍ᐢ。•༝•。ᐢ₎', 'ヽ(・ω・*)', '( |||| ᐢ˙꒳˙ᐢ )'];
const searchChange = (e: Event) => { const searchChange = (e: Event) => {
if (refresh === false) return; if (refresh === false) return;
const value = (e.target as HTMLInputElement).value; const value = (e.target as HTMLInputElement).value;
if (value.length === 0) return; if (value.length === 0) return;
refresh = false; refresh = false;
let xhr = new XMLHttpRequest(); let xhr = new XMLHttpRequest();
// xhr.open('GET', `/api/search?q=${value}`); // xhr.open('GET', `/api/search?q=${value}`);
// xhr.send(); // xhr.send();
// xhr.onload = () => { // xhr.onload = () => {
// setTimeout(() => {q // setTimeout(() => {q
// refresh = true; // refresh = true;
// }, 1000); // }, 1000);
// }; // };
setTimeout(() => { setTimeout(() => {
suggest.textContent = emojis[Math.floor(Math.random() * emojis.length)] + 'ミジッソウダヨ...'; suggest.textContent = emojis[Math.floor(Math.random() * emojis.length)] + 'ミジッソウダヨ...';
setTimeout(() => { setTimeout(() => {
refresh = true; refresh = true;
}, 1000); }, 1000);
}, Math.random() * 100); }, Math.random() * 100);
}; };
const searchKeydown = (e: KeyboardEvent) => { const searchKeydown = (e: KeyboardEvent) => {
if (e.key !== 'Enter') return; if (e.key !== 'Enter') return;
// const input = e.target as HTMLInputElement; // const input = e.target as HTMLInputElement;
// const value = input.value; // const value = input.value;
// if (value.length > 0) { // if (value.length > 0) {
// window.location.href = `/search?s=${value}`; // window.location.href = `/search?s=${value}`;
// } // }
suggest.textContent = emojis[Math.floor(Math.random() * emojis.length)] + 'アン?'; suggest.textContent = emojis[Math.floor(Math.random() * emojis.length)] + 'アン?';
}; };
</script> </script>
<svelte:head> <svelte:head>
<title>Home | Blog | HareWorks</title> <title>Home | Blog | HareWorks</title>
<meta name="description" content="Hareの個人ブログです。" /> <meta name="description" content="Hareの個人ブログです。" />
<meta property="og:title" content="Home - HareWorks" /> <meta property="og:title" content="Home - HareWorks" />
<meta property="og:description" content="Hareの個人ブログです。" /> <meta property="og:description" content="Hareの個人ブログです。" />
<meta property="og:image" content="/img/logo.png" /> <meta property="og:image" content="/img/logo.png" />
<meta property="og:url" content={`https://blog.hare.works/`} /> <meta property="og:url" content={`https://blog.hare.works/`} />
</svelte:head> </svelte:head>
<div class="container"> <div class="container">
<div class="controls" > </div> <div class="controls"></div>
<main> <main>
<h1>blog.hareworks.net</h1> <h1>blog.hareworks.net</h1>
<p> <p>
このブログはHareの個人ブログです。プログラミング、情報技術全般、デザイン、その他興味のあることについて書いています。 このブログはHareの個人ブログです。プログラミング、情報技術全般、デザイン、その他興味のあることについて書いています。
</p> </p>
<div class="links"> <div class="links">
<ul> <ul>
<li><a href="/about">ABOUT</a></li> <li><a href="/about">ABOUT</a></li>
<li><a href="/contact">CONTACT</a></li> <li><a href="/contact">CONTACT</a></li>
<li><a href="/discord">DISCORD</a></li> <li><a href="/discord" target="_blank">DISCORD</a></li>
</ul> </ul>
</div> </div>
<div class="notice"> <div class="notice">
<p>( ᐢ˙꒳˙ᐢ ) ← cute</p> <p>( ᐢ˙꒳˙ᐢ ) ← cute</p>
</div> </div>
<div class="serch"> <div class="serch">
<div class="box"> <div class="box">
<input <input
type="text" type="text"
placeholder="Search" placeholder="Search"
on:focus={() => { on:focus={() => {
suggest.classList.remove('hidden'); suggest.classList.remove('hidden');
}}
}} on:blur={() => {
on:blur={() => { suggest.classList.add('hidden');
suggest.classList.add('hidden'); }}
}} on:input={searchChange}
on:input={searchChange} on:keydown={searchKeydown}
on:keydown={searchKeydown} bind:this={searchInput}
bind:this={searchInput} />
/> </div>
</div> <div class="suggest hidden" bind:this={suggest}></div>
<div class="suggest hidden" bind:this={suggest}></div> </div>
</div> <div class="recent">
<div class="recent"> <h2>RECENT<span>updated: <FormattedDate date={data.updated} /></span></h2>
<h2>RECENT<span>updated: {data.updated}</span></h2> <ul>
<ul> {#each data.recent as post}
{#each data.recent as post} <li>
<li> <a href={post.link}>{post.title} - {post.date}</a>
<a href={post.link}>{post.title} - {post.date}</a> </li>
</li> {/each}
{/each} </ul>
</ul> </div>
</div> <div class="tags">
<div class="tags"> <h2>TAGS</h2>
<h2>TAGS</h2> <ul>
<ul> {#each data.tags as tag}
{#each data.tags as tag} <li>
<li> <button on:click={() => (searchInput.value = tag)}>{tag}</button>
<button on:click={() => (searchInput.value = tag)}>{tag}</button> </li>
</li> {/each}
{/each} </ul>
</ul> </div>
</div> <Footer />
<!-- <Footer mode="home" /> --> </main>
</main>
</div> </div>
<style lang="scss"> <style lang="scss">
:global(body) { :global(body) {
overflow: hidden; overflow: hidden;
background-color: var(--background-primary); background-color: var(--background-primary);
background-size: cover; background-size: cover;
background-blend-mode: overlay; background-blend-mode: overlay;
} }
.container { .container {
overflow: hidden; overflow: hidden;
width: 100vw; width: 100vw;
height: 100dvh; height: 100dvh;
backdrop-filter: blur(2px); backdrop-filter: blur(2px);
overflow: auto; overflow: auto;
} }
.controls { .controls {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.5);
} }
main { main {
border: 1px solid var(--line-primary); border: 1px solid var(--line-primary);
border-top: none; border-top: none;
border-bottom: none; border-bottom: none;
margin: 0 auto; margin: 0 auto;
padding: 60px 8px; padding: 60px 8px;
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
max-width: 1000px; max-width: 1000px;
height: 100dvh; height: 100dvh;
color: white; color: white;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
> div { > div {
margin: 10px 0; margin: 10px 0;
} }
h1 { h1 {
font-size: 2rem; font-size: 2rem;
font-weight: 400; font-weight: 400;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
p { p {
width: 80%; width: 80%;
} }
.links { .links {
margin-left: auto; margin-left: auto;
width: 80%; width: 80%;
ul { ul {
list-style: none; list-style: none;
padding: 10px; padding: 10px;
margin: 0; margin: 0;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: end; justify-content: end;
gap: 4px; gap: 4px;
border-top: 1px solid var(--line-primary); border-top: 1px solid var(--line-primary);
li { li {
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
padding: 0 3px 0 3px; padding: 0 3px 0 3px;
a { a {
text-decoration: none; text-decoration: none;
color: white; color: white;
box-sizing: border-box; box-sizing: border-box;
} }
} }
} }
} }
.notice { .notice {
padding: 5px 0; padding: 5px 0;
border-bottom: 1px solid var(--line-primary); border-bottom: 1px solid var(--line-primary);
p { p {
padding: 15px 0; padding: 15px 0;
text-align: center; text-align: center;
width: 100%; width: 100%;
margin: 0; margin: 0;
background-color: rgba(105, 105, 105, 0.1); background-color: rgba(105, 105, 105, 0.1);
} }
} }
.serch { .serch {
width: 100%; width: 100%;
.box { .box {
display: flex; display: flex;
&::before { &::before {
content: ' '; content: ' ';
position: relative; position: relative;
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 30%; width: 30%;
border-bottom: 1px solid var(--line-primary); border-bottom: 1px solid var(--line-primary);
} }
input[type='text'] { input[type='text'] {
display: inline; display: inline;
width: 70%; width: 70%;
margin-left: auto; margin-left: auto;
box-sizing: border-box; box-sizing: border-box;
padding: 10px; padding: 10px;
background-color: transparent; background-color: transparent;
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
border: 1px solid var(--line-primary); border: 1px solid var(--line-primary);
border-bottom: none; border-bottom: none;
border-right: none; border-right: none;
color: white; color: white;
&:active, &:active,
&:focus { &:focus {
outline: none; outline: none;
} }
} }
} }
.suggest { .suggest {
display: block; display: block;
margin-left: 30%; margin-left: 30%;
width: 70%; width: 70%;
height: 30px; height: 30px;
overflow: hidden; overflow: hidden;
border-bottom: 1px solid var(--line-primary); border-bottom: 1px solid var(--line-primary);
transition: 0.5s ease-in-out; transition: 0.5s ease-in-out;
transition-property: height border-bottom; transition-property: height border-bottom;
&.hidden { &.hidden {
height: 0; height: 0;
border-bottom: 1px solid transparent; border-bottom: 1px solid transparent;
} }
} }
} }
h2 { h2 {
display: block; display: block;
font-size: 1.5rem; font-size: 1.5rem;
font-weight: 400; font-weight: 400;
margin: 5px; margin: 5px;
padding: 0 20px 0 10px; padding: 0 20px 0 10px;
border-left: 1px solid var(--line-primary); border-left: 1px solid var(--line-primary);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
> span { > span {
padding-left: 30px; padding-left: 30px;
font-size: 0.8rem; font-size: 0.8rem;
color: rgba(255, 255, 255, 0.5); color: rgba(255, 255, 255, 0.5);
} }
} }
a { a {
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
} }
button { button {
font-size: 1rem; font-size: 1rem;
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
border: none; border: none;
color: white; color: white;
background-color: transparent; background-color: transparent;
border-bottom: 1px solid transparent; border-bottom: 1px solid transparent;
&:hover { &:hover {
border-bottom: 1px solid var(--line-primary); border-bottom: 1px solid var(--line-primary);
} }
} }
ul { ul {
list-style: none; list-style: none;
padding: 0 0 0 30px; padding: 0 0 0 30px;
margin: 0; margin: 0;
li { li {
padding: 5px 0; padding: 5px 0;
} }
} }
.recent { .recent {
margin-top: 20px; margin-top: 20px;
} }
.tags { .tags {
ul { ul {
display: flex; display: flex;
gap: 3px; gap: 3px;
li { li {
font-size: 1rem; font-size: 1rem;
padding: 3px 5px; padding: 3px 5px;
} }
} }
} }
} }
a { a {
text-decoration: none; text-decoration: none;
border-bottom: 1px solid var(--line-primary); border-bottom: 1px solid var(--line-primary);
color: white; color: white;
box-sizing: border-box; box-sizing: border-box;
} }
@media (max-width: 1000px) { @media (max-width: 1000px) {
main { main {
width: 100%; width: 100%;
flex-direction: column; flex-direction: column;
gap: 20px; gap: 20px;
} }
.notice { .notice {
p { p {
padding: 10px 0; padding: 10px 0;
} }
} }
} }
</style> </style>