184 lines
3.5 KiB
Plaintext
184 lines
3.5 KiB
Plaintext
---
|
|
import Layout from "@/layouts/Layout.astro";
|
|
import Card from "@/components/Card.astro";
|
|
import details from "@/constants/details";
|
|
import links from "@/constants/links";
|
|
import contacts from "@/constants/contacts";
|
|
import supports from "@/constants/supports";
|
|
import { Image } from "astro:assets";
|
|
---
|
|
|
|
<Layout>
|
|
<div class="profile">
|
|
<Image
|
|
width="20"
|
|
height="20"
|
|
loading="eager"
|
|
src={new URL("/avatar.png", Astro.url.origin).toString()}
|
|
alt="アバター"
|
|
/>
|
|
|
|
<div>
|
|
<span>
|
|
Last2014
|
|
</span>
|
|
|
|
<p>
|
|
ウェブ開発をしてる小学生です。<br />
|
|
TypeScriptをメインに色々作っています。
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<span id="detail">詳細</span>
|
|
|
|
<div class="table">
|
|
<table>
|
|
<tbody>
|
|
{details.map((detail, i) => (
|
|
<tr class={i === 0 || i === details.length - 1
|
|
? "edge"
|
|
: ""}
|
|
>
|
|
<td>{detail.title}</td>
|
|
<td>{detail.description}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<span id="link">リンク</span>
|
|
|
|
{links.map((link) => (
|
|
<Card imgLoading="eager" {...link} />
|
|
))}
|
|
</div>
|
|
|
|
<div class="section">
|
|
<span id="support">支援</span>
|
|
|
|
{supports.map((link) => (
|
|
<Card {...link} canDarkInvert isFullWidth />
|
|
))}
|
|
</div>
|
|
|
|
<div class="section">
|
|
<span id="contant">連絡先</span>
|
|
|
|
{contacts.map((contact) => (
|
|
<Card canDarkInvert {...contact} isFullWidth />
|
|
))}
|
|
</div>
|
|
</Layout>
|
|
|
|
<style scoped>
|
|
.profile {
|
|
display: flex;
|
|
width: 80dvw;
|
|
min-width: 20rem;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.profile img {
|
|
width: 4rem;
|
|
height: 4rem;
|
|
border-radius: 100%;
|
|
border: 1px solid var(--border-color);
|
|
flex-shrink: 0;
|
|
user-select: none;
|
|
-webkit-user-select: none;
|
|
}
|
|
|
|
.profile div {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.profile div span {
|
|
font-size: 1.25rem;
|
|
font-weight: 450;
|
|
}
|
|
|
|
.profile div p {
|
|
font-weight: 350;
|
|
}
|
|
|
|
.section {
|
|
min-width: 20rem;
|
|
width: 80dvw;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.75rem;
|
|
}
|
|
|
|
.section span {
|
|
width: 100%;
|
|
font-weight: bold;
|
|
font-size: 2rem;
|
|
user-select: none;
|
|
-webkit-user-select: none;
|
|
}
|
|
|
|
.section .table {
|
|
width: 100%;
|
|
overflow: hidden;
|
|
padding: 0.75rem 1rem;
|
|
background-color: #ffffff;
|
|
color: #000000;
|
|
padding: 0.75rem 1rem;
|
|
border-radius: 1rem;
|
|
}
|
|
|
|
.section table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.section .table table tbody tr,
|
|
.section .table table tbody td {
|
|
padding: 0.25rem;
|
|
font-size: 1.1rem;
|
|
}
|
|
|
|
.section .table table tbody tr {
|
|
border-top: 1px solid var(--border-color);
|
|
border-bottom: 1px solid var(--border-color);
|
|
}
|
|
|
|
.section .table table tbody tr.edge {
|
|
border: none;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
.section .table {
|
|
background-color: #000000;
|
|
color: #ffffff;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
const birthday = new Date("2014-12-08");
|
|
|
|
const getAge = () => {
|
|
const now = new Date();
|
|
let age = now.getFullYear() - birthday.getFullYear();
|
|
const m = now.getMonth() - birthday.getMonth();
|
|
|
|
if (m < 0 || (m === 0 && now.getDate() < birthday.getDate())) {
|
|
age--;
|
|
}
|
|
|
|
return age;
|
|
}
|
|
|
|
const cardDescriptions = Array.from(document.querySelectorAll("td"));
|
|
const ageData = cardDescriptions.filter(el => el.textContent === "")[0];
|
|
ageData.textContent = getAge() + "歳";
|
|
</script> |