added header, footer, eslint/prettier, and typedoc

This commit is contained in:
2024-09-13 17:06:10 +09:00
parent 845418da60
commit a7dc8d6c8f
56 changed files with 16207 additions and 11147 deletions

165
components/DropDown.vue Normal file
View File

@@ -0,0 +1,165 @@
<script setup lang="ts">
import type { DropDownProperty } from "#imports";
const property = defineProps<DropDownProperty>();
const isOpen = ref<boolean>(false);
const showInMobile = ref<boolean>(property.showInMobile);
const { viewPortType } = useWindowDimensions();
const listAlignment = ref<typeof DropDownAlignment | number>(
property.alignment | DropDownAlignment.Left
);
const alignmentClass = computed(() => ({
"left-aligned-list": listAlignment.value === DropDownAlignment.Left,
"right-aligned-list": listAlignment.value === DropDownAlignment.Right,
}));
const handleMouseHoverEvent = (event: Event) => {
const eventType = event.type;
if (property.mode !== DropDownMode.onMouseHover) return;
if (eventType === "mouseover") {
isOpen.value = true;
} else if (eventType === "mouseleave") {
isOpen.value = false;
}
return;
};
const handleClickEvent = () => {
if (property.mode !== DropDownMode.onClick) return;
isOpen.value = !isOpen.value;
return;
};
const handleFocusOutEvent = () => {
if (property.mode !== DropDownMode.onClick) return;
isOpen.value = false;
return;
};
</script>
<template>
<div
class="dropdown-menu"
:class="alignmentClass"
v-on="{
mouseover: handleMouseHoverEvent,
mouseleave: handleMouseHoverEvent,
}"
v-if="
(showInMobile === true && viewPortType !== ViewPortType.DESKTOP) ||
(showInMobile === false && viewPortType !== ViewPortType.MOBILE)
"
>
<button
class="dropdown-label"
v-on="{
click: handleClickEvent,
focusout: handleFocusOutEvent,
}"
>
{{ property.label }}
</button>
<Transition name="dropdown-fade">
<div class="dropdown-item-list" v-if="isOpen">
<ul>
<li
v-for="entry in property.entries"
:key="property.entries.indexOf(entry)"
>
<NuxtLink :to="entry.link">{{ entry.text }}</NuxtLink>
</li>
</ul>
</div>
</Transition>
</div>
</template>
<style scoped>
.dropdown-fade-enter-active,
.dropdown-fade-leave-active {
transition: opacity 0.2s ease;
}
.dropdown-fade-enter-from,
.dropdown-fade-leave-to {
opacity: 0;
}
.dropdown-menu {
display: inline-block;
width: fit-content;
position: relative;
}
.dropdown-label {
background: none;
width: fit-content;
padding: 1rem 2rem;
border: transparent solid 3px;
font-size: 1em;
font-weight: bold;
color: var(--neptune1);
}
.dropdown-label:hover {
cursor: pointer;
color: var(--andromeda);
border-top: currentColor solid 3px;
transition: 0.2s linear;
}
.left-aligned-list {
text-align: left;
& .dropdown-item-list {
left: 0;
}
}
.right-aligned-list {
text-align: right;
& .dropdown-item-list {
right: 0;
text-align: left;
}
}
.dropdown-item-list {
display: block;
background: var(--neptune1);
color: var(--starlight);
font-weight: bold;
position: absolute;
top: auto;
min-width: 100%;
width: fit-content;
text-wrap: nowrap;
& ul {
list-style: none;
padding: 0 0.25rem;
}
& ul li {
margin: 0.5rem 0;
transition: 0.2s linear;
}
& ul li:first-child {
margin-top: 0;
}
& ul li:last-child {
margin-bottom: 0;
}
& ul li a {
display: block;
width: 100%;
text-decoration: none;
color: currentColor;
padding: 0 0.5rem;
}
& ul li:hover a {
text-decoration: currentColor underline dashed;
text-decoration-thickness: 2px;
}
}
</style>

View File

@@ -1,9 +1,7 @@
<script setup lang="ts"></script>
<template>
<div>
Component: newslist
</div>
<div>Component: newslist</div>
</template>
<style scoped></style>

View File

@@ -1,9 +1,274 @@
<script setup lang="ts"></script>
<script setup lang="ts">
import LogoSVG from "public/sera-logo-no-text.svg";
import SiteInfo from "assets/siteinfo.json";
const showTwitterIcon = ref<boolean>(false);
const getTimeRequest = await useFetch("/api/getTime");
const time: Date = new Date(getTimeRequest.data.value as number);
const timeGenerated: string = time.toLocaleString("ja-JP-u-ca-japanese", {
dateStyle: "medium",
timeStyle: "short",
});
const showThePast = (event: Event) => {
const eventType = event.type;
if (eventType === "mouseover") {
showTwitterIcon.value = true;
} else if (eventType === "mouseleave") {
showTwitterIcon.value = false;
}
};
</script>
<template>
<div>
Component: TheFooter
</div>
<footer>
<div class="footer-wrapper">
<div class="logo">
<LogoSVG />
</div>
<div class="top-column">
<div class="summary">
<h3>{{ SiteInfo.clubNameLong }}</h3>
<p>
宇宙分野に興味ある学生が<wbr />集い<wbr />宇宙理工学に<wbr />関する知識を<wbr />身に付けると共に<wbr />
宇宙分野に関連する<wbr />各種競技会へ<wbr />参加して<wbr />人間力と実践力を<wbr />養うことを目的に<wbr />活動しています
</p>
<NuxtLink to="/about/sera"
>About {{ SiteInfo.clubNameAbbreviation }}</NuxtLink
>
</div>
<div class="links">
<ul>
<li>
<NuxtLink to="/"> Home </NuxtLink>
</li>
<li>
<NuxtLink to="/news"> News </NuxtLink>
</li>
<li>
<NuxtLink to="/projects"> Projects </NuxtLink>
<ul>
<li>
<NuxtLink to="/projects/rocket">
Rocket
</NuxtLink>
</li>
<li>
<NuxtLink to="/projects/cansat">
CanSat
</NuxtLink>
</li>
<li>
<NuxtLink to="/projects/kosen-x">
CubeSat Kosen-x
</NuxtLink>
</li>
<li>
<NuxtLink to="/projects/edu-robot">
Edu-Robot
</NuxtLink>
</li>
</ul>
</li>
<li>
<NuxtLink to="/about/sera">
About {{ SiteInfo.clubNameAbbreviation }}
</NuxtLink>
</li>
</ul>
</div>
<div class="sns-list">
<h3>
{{ SiteInfo.clubNameAbbreviation
}}<wbr /><wbr />フォロー<wbr />する
</h3>
<ul>
<li>
<NuxtLink
to="https://twitter.com/SERA_NITGC"
target="_blank"
v-on="{
mouseover: showThePast,
mouseleave: showThePast,
}"
>
<Transition name="show-the-past">
<Icon
name="simple-icons:x"
v-show="!showTwitterIcon"
/>
</Transition>
<Transition name="show-the-past">
<Icon
name="simple-icons:twitter"
v-show="showTwitterIcon"
/>
</Transition>
</NuxtLink>
</li>
<li>
<NuxtLink
to="https://www.instagram.com/sera_nitgc_official"
target="_blank"
>
<Icon name="simple-icons:instagram" />
</NuxtLink>
</li>
</ul>
</div>
</div>
<div class="bottom-column">
<p>最終更新: {{ timeGenerated }}</p>
<p>
このHPは{{
SiteInfo.clubNameAbbreviation
}}の学生が開発運営しています
</p>
<p>
© {{ SiteInfo.copyrightYear }} NIT-GC
{{ SiteInfo.clubNameAbbreviation }} All Rights Reserved.
</p>
</div>
</div>
</footer>
</template>
<style scoped></style>
<style scoped>
.show-the-past-enter-active,
.show-the-past-leave-active {
transition: opacity 30s cubic-bezier(1, 0, 1, 0.75);
}
.show-the-past-enter-from,
.show-the-past-leave-to {
opacity: 0;
}
footer {
background: var(--ocean-blue);
color: var(--sunlight);
width: 100vw;
}
.footer-wrapper {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto auto auto;
max-width: 1400px;
width: 90%;
margin: auto;
padding: 2rem 0;
& h3 {
text-transform: uppercase;
}
& p {
font-size: 0.75em;
}
& a {
text-decoration: none;
color: var(--sunlight);
}
& a:hover {
text-decoration: currentColor underline dashed;
text-decoration-thickness: 2px;
}
}
.logo {
height: fit-content;
& svg {
width: auto;
height: 56px;
}
}
.top-column {
display: grid;
grid-template-columns: 2fr 5fr 1fr;
grid-template-rows: 1fr;
padding-bottom: 1rem;
border-bottom: var(--sunlight) solid 3px;
}
.links ul {
list-style: none;
font-weight: 600;
& li {
margin: 0.25rem 0;
}
& > li:first-child {
margin-top: 0;
}
& > li:last-child {
margin-bottom: 0;
}
}
.sns-list h3 {
word-break: keep-all;
overflow-wrap: break-word;
}
.sns-list ul {
list-style: none;
display: flex;
padding: 0;
li {
margin-right: 0.5rem;
a span {
width: 48px;
height: 48px;
}
}
li:first-child {
a {
position: relative;
display: block;
width: 48px;
height: 48px;
}
a span {
position: absolute;
}
}
li:last-child {
margin-right: 0;
}
li:hover {
transform: scale(120%);
transition: all 0.2s ease;
}
}
.bottom-column {
display: flex;
margin: 1rem auto;
& > * {
margin: 0 0.5rem;
}
}
/* Phone Style */
@media screen and (max-width: 640px) {
.top-column {
grid-template-columns: auto;
grid-template-rows: auto auto auto;
}
.summary {
word-break: keep-all;
overflow-wrap: break-word;
}
.sns-list {
display: block;
margin: auto;
}
.bottom-column {
display: block;
& > * {
margin: 0.5rem 0;
}
}
}
</style>

View File

@@ -1,44 +1,101 @@
<script setup lang="ts"></script>
<script setup lang="ts">
import LogoSVG from "public/sera-logo-no-text.svg";
import type { DropDownEntry } from "~/utils/dropDown";
const exploreDropDownEntries: Array<DropDownEntry> = [
{ text: "Home", link: "/" },
{ text: "Projects", link: "/projects" },
{ text: "CanSat", link: "/projects/cansat" },
{ text: "Edu-Robot", link: "/projects/edu-robot" },
{ text: "CubeSat Kosen-X", link: "/projects/kosen-x" },
{ text: "Rocket", link: "/projects/rocket" },
{ text: "About", link: "/about" },
];
const mediaDropDownEntries: Array<DropDownEntry> = [
{ text: "News", link: "/news" },
{ text: "Gallery", link: "/about/gallery" },
];
</script>
<template>
<div>
<ul>
<li>
<NuxtLink to="/news">
News
</NuxtLink>
</li>
<li>
<NuxtLink to="/projects">
Projects
</NuxtLink>
</li>
<li>Link</li>
<li>Contact</li>
<li>
<NuxtLink to="/about">
About SERA
</NuxtLink>
</li>
</ul>
<NuxtLink to="/">
<img ref="/sera-logo-no-text.svg">
</NuxtLink>
<ul>
<li>
<NuxtLink to="/">For non-member</NuxtLink>
</li>
<li>
<NuxtLink to="/">Info</NuxtLink>
</li>
</ul>
</div>
<header>
<div class="navigation-menu">
<div id="header-left">
<DropDown
label="Explore"
:mode="DropDownMode.onClick"
:alignment="DropDownAlignment.Left"
:entries="exploreDropDownEntries"
:show-in-mobile="false"
/>
</div>
<div id="logo-link">
<NuxtLink to="/">
<LogoSVG role="img" id="logo-img" />
</NuxtLink>
</div>
<div id="header-right">
<DropDown
label="Media"
:mode="DropDownMode.onClick"
:alignment="DropDownAlignment.Right"
:entries="mediaDropDownEntries"
:show-in-mobile="false"
/>
</div>
</div>
</header>
</template>
<style scoped>
div {
display: grid;
grid-row: 1fr;
grid-template-columns: 1fr 1fr 1fr;
.navigation-menu {
display: grid;
grid-template-rows: 1fr;
grid-template-columns: 1fr 1fr 1fr;
line-height: 1.8;
padding: 1.25rem 3rem;
height: 64px;
background: var(--deep-space);
}
#header-left,
#header-right {
display: flex;
}
#header-left {
flex-direction: row;
}
#header-right {
flex-direction: row-reverse;
& ul {
list-style: none;
display: flex;
justify-items: space-between;
}
}
#logo-link {
display: flex;
justify-content: center;
& a {
width: fit-content;
background: var(--moonlight);
padding: 0.5rem;
margin-top: -0.5rem;
border-radius: 3rem;
filter: drop-shadow(0 0 0.5rem var(--moonlight));
}
& a:hover {
transform: scale(110%);
transition: 0.2s ease-in;
}
}
#logo-img {
width: 128px;
height: auto;
}
</style>