diff --git a/src/pages/careers/molecule/Timeline.module.scss b/src/pages/careers/molecule/Timeline.module.scss
index 6e102d0..c92e886 100644
--- a/src/pages/careers/molecule/Timeline.module.scss
+++ b/src/pages/careers/molecule/Timeline.module.scss
@@ -6,6 +6,11 @@
flex-direction: column;
width: calc(100% - 5em);
margin-left: 5em;
+
+ @include layout.for(tablet) {
+ width: 100%;
+ margin-left: 0;
+ }
}
.main-timeline {
@@ -16,11 +21,6 @@
border-left: 3px solid darken(color.get-theme-color(background-alt), 10);
- @include layout.for(tablet) {
- width: 100%;
- margin-left: 0;
- }
-
}
.scope-out {
diff --git a/src/pages/main/Main.tsx b/src/pages/main/Main.tsx
index 84fa08c..ae9f014 100644
--- a/src/pages/main/Main.tsx
+++ b/src/pages/main/Main.tsx
@@ -2,6 +2,7 @@ import React from "react";
import { PageWrapper } from "~/comps/layout/PageWrapper";
import { LogoImage } from "~/comps/shared/LogoImage";
import { SimpleButton } from "~/comps/shared/SimpleButton";
+import { quickNavigations } from "../router/routing";
import styles from "./Main.module.scss";
@@ -10,9 +11,9 @@ export const Main = () => (
-
-
-
+ {quickNavigations.map((nav, i) => (
+
+ ))}
diff --git a/src/pages/router/routing.ts b/src/pages/router/routing.ts
index 2eacba7..2c45ecb 100644
--- a/src/pages/router/routing.ts
+++ b/src/pages/router/routing.ts
@@ -4,6 +4,7 @@ import { Main } from "~/pages/main/Main";
import { About } from "../about/About";
import { Skills } from "../skills/Skills";
import { Careers } from "../careers/Careers";
+import { Works } from "../works/Works";
export type QuickNavigation = {
path: string;
@@ -16,10 +17,12 @@ export const routingTable: RouteProps[] = [
{ path: "/about", component: About, exact: true },
{ path: "/skills", component: Skills, exact: true },
{ path: "/careers", component: Careers, exact: true },
+ { path: "/works", component: Works, exact: true },
];
export const quickNavigations: QuickNavigation[] = [
{ path: "/about", caption: "自己紹介" },
{ path: "/skills", caption: "スキル" },
{ path: "/careers", caption: "実績" },
+ { path: "/works", caption: "作ったもの" },
];
diff --git a/src/pages/works/Works.tsx b/src/pages/works/Works.tsx
new file mode 100644
index 0000000..36aa714
--- /dev/null
+++ b/src/pages/works/Works.tsx
@@ -0,0 +1,13 @@
+import React from "react";
+import { PageWrapper } from "~/comps/layout/PageWrapper";
+import { Heading } from "~/comps/shared/Heading";
+import { WorksList } from "./molecules/WorksList";
+
+export const Works = () => (
+
+
+ 作ったもの
+
+
+
+);
diff --git a/src/pages/works/atoms/Work.module.scss b/src/pages/works/atoms/Work.module.scss
new file mode 100644
index 0000000..399f5a4
--- /dev/null
+++ b/src/pages/works/atoms/Work.module.scss
@@ -0,0 +1,59 @@
+@use "~/styling/color.module.scss";
+
+.container {
+ position: relative;
+
+ display: flex;
+ flex-direction: column;
+ gap: 0.3em;
+
+ padding: 0.5em 1em;
+ overflow: hidden;
+
+ background-color: color.get-theme-color(background-alt);
+}
+
+.work-info {
+ display: flex;
+ flex-direction: column;
+}
+
+.title {
+ font-size: 1.8em;
+ font-weight: 700;
+
+ overflow-wrap: anywhere;
+}
+
+.tags {
+ font-size: 0.85em;
+ line-height: 105%;
+
+ color: color.get-theme-color(text-color-secondary);
+}
+
+.url {
+ font-size: 0.85em;
+ overflow-wrap: anywhere;
+}
+
+.separator {
+ border-bottom: 2px dotted darken(color.get-theme-color(background-alt), 10);
+}
+
+.status-band {
+ position: absolute;
+ top: 1.5em;
+ right: -2.75em;
+
+ width: 10em;
+ transform: rotate(45deg);
+
+ background-color: darken(color.get-theme-color(background-alt), 15);
+ box-shadow: 0 0 3px color.get-theme-color(shadow-color);
+ color: white;
+
+ padding: 0.1em 0;
+
+ text-align: center;
+}
diff --git a/src/pages/works/atoms/Work.tsx b/src/pages/works/atoms/Work.tsx
new file mode 100644
index 0000000..721c65b
--- /dev/null
+++ b/src/pages/works/atoms/Work.tsx
@@ -0,0 +1,36 @@
+import React from "react";
+import { Link } from "react-router-dom";
+import { Status, Work as WorkEntity } from "~/api/graphql/autogen/scheme";
+
+import styles from "./Work.module.scss";
+
+const statusToCaption: { [key in Status]: string } = {
+ ADVANCING: "積極的に開発中",
+ ARCHIVED: "開発終了",
+ COMPLETED: "完成",
+ DEVELOPING: "開発途中",
+ MAINTENANCING: "メンテナンス中",
+};
+
+export type WorkProps = WorkEntity;
+export const Work: React.VFC = (props) => (
+
+
+ {props.name}
+ {props.tags.join(" / ")}
+
+
+
{props.description}
+
+
+ {props.repoUrl == null ? (
+ ソースコードは非公開です.
+ ) : (
+
+ {props.repoUrl}
+
+ )}
+
+
{statusToCaption[props.status]}
+
+);
diff --git a/src/pages/works/controller.ts b/src/pages/works/controller.ts
new file mode 100644
index 0000000..44f8a89
--- /dev/null
+++ b/src/pages/works/controller.ts
@@ -0,0 +1,17 @@
+import { gql, QueryResult, useQuery } from "@apollo/client";
+import { Work } from "~/api/graphql/autogen/scheme";
+
+const FetchWork = gql`
+ query FetchWork {
+ works {
+ name
+ description
+ repoUrl
+ tags
+ status
+ }
+ }
+`;
+export type FetchWorkResponse = { works: Work[] };
+export const useWorksAPI = (): QueryResult =>
+ useQuery(FetchWork);
diff --git a/src/pages/works/molecules/WorksList.module.scss b/src/pages/works/molecules/WorksList.module.scss
new file mode 100644
index 0000000..be080bf
--- /dev/null
+++ b/src/pages/works/molecules/WorksList.module.scss
@@ -0,0 +1,13 @@
+@use "~/styling/layout.module.scss";
+
+.container {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ grid-gap: 1em;
+
+ width: 100%;
+
+ @include layout.for(tablet) {
+ grid-template-columns: 1fr;
+ }
+}
diff --git a/src/pages/works/molecules/WorksList.tsx b/src/pages/works/molecules/WorksList.tsx
new file mode 100644
index 0000000..df1e120
--- /dev/null
+++ b/src/pages/works/molecules/WorksList.tsx
@@ -0,0 +1,22 @@
+import React from "react";
+import { AwaitFetch } from "~/comps/shared/AwaitFetch";
+import { Work } from "../atoms/Work";
+import { useWorksAPI } from "../controller";
+
+import styles from "./WorksList.module.scss";
+
+export const WorksList = () => {
+ const { loading, error, data } = useWorksAPI();
+
+ return (
+
+ {(data) => (
+
+ {data.works.map((work, i) => (
+
+ ))}
+
+ )}
+
+ );
+};