Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feature/authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
Shion1305 committed Mar 12, 2024
2 parents cecbcdc + 717f3a3 commit f45982b
Show file tree
Hide file tree
Showing 19 changed files with 776 additions and 35 deletions.
67 changes: 34 additions & 33 deletions proto/golang/pb_out/main.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion proto/src/main.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ message Tag {

message Milestone {
string user_id = 1;
string event_id = 2;
string milestone_id = 2;
string title = 3;
string content = 4;
string image_hash = 5; // GCS内のファイル名
Expand Down
2 changes: 1 addition & 1 deletion proto/typescript/pb_out/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface Tag {

export interface Milestone {
userId: string;
eventId: string;
milestoneId: string;
title: string;
content: string;
/** GCS内のファイル名 */
Expand Down
Binary file added public/milestone-sample.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions src/app/career-edit/[userId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"use client";

import EditingCareerCalendar from "@/components/EditingCareerCalendar";
import { useParams } from "next/navigation";
import React from "react";

const CareerEdit = () => {
const params = useParams();
const userId = Array.isArray(params.userId) ? null : params.userId;

return (
<div className="p-5">
{userId && <EditingCareerCalendar userId={userId} />}
{!userId && <p>問題が発生しました。</p>}
</div>
);
};

export default CareerEdit;
27 changes: 27 additions & 0 deletions src/app/future-time-line/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use client'
import React from 'react'
import milestones from '@/sample-data/milestones.json'
import FutureTimeLine from '@/components/organisms/FutureTimeLine'

export type MileStone = {
userId: string;
milestoneId: string;
title: string;
content: string;
/** GCS内のファイル名 */
imageHash: string;
/** RFC3339 */
beginDate: string;
/** RFC3339 */
finishDate: string;
}

const FutureTimeLinePage = () => {
return (
<main className="flex min-h-screen flex-col items-center justify-between md:p-24">
<FutureTimeLine milestones={milestones} />
</main>
)
}

export default FutureTimeLinePage
73 changes: 73 additions & 0 deletions src/components/EditingCareerCalendar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"use client";

import { useCallback, useState } from "react";
import EditingCareerEvent from "./EditingCareerEvent";
import milestones from "@/sample-data/milestones.json";
import { Milestone } from "../../proto/typescript/pb_out/main";

// とりあえず100年分のカレンダーを表示
const FULL_YEAR = 100;
const START_YEAR = 2022;

type Props = {
userId: string;
};

const EditingCareerCalendar = ({ userId }: Props) => {
const array = new Array(FULL_YEAR).fill(0);
const [lifeEvents, setLifeEvents] = useState<Milestone[]>(
milestones.filter((m) => m.userId === userId)
);

const updateLifeEvent = useCallback(
(newLifeEvent: Milestone) => {
setLifeEvents(
lifeEvents.map((l) =>
l.milestoneId === newLifeEvent.milestoneId ? newLifeEvent : l
)
);
},
[lifeEvents]
);

return (
<div
className="grid"
style={{ gridAutoRows: "10px", gridAutoColumns: "100px auto 20px" }}
>
{array.map((_, index) => (
<div
className="border-r-2 col-start-1 col-end-2"
style={{
gridRow: `${index * 12 + 1} / span 12`,
}}
key={`year-${index}`}
>
<p className="text-right mr-5">{START_YEAR + index}</p>
</div>
))}
{array.map((_, index) => (
<div
className="border-y-[0.5px] col-start-2 col-end-4"
style={{
gridRow: `${index * 12 + 1} / span 12`,
}}
key={`year-${index}`}
>
{" "}
</div>
))}
{lifeEvents.map((lifeEvent, index) => {
return (
<EditingCareerEvent
lifeEvent={lifeEvent}
updateLifeEvent={updateLifeEvent}
key={`lifeEvent-${index}`}
/>
);
})}
</div>
);
};

export default EditingCareerCalendar;
55 changes: 55 additions & 0 deletions src/components/EditingCareerEvent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client";

import useEditingCareerEvent from "@/hooks/useEditingCareerEvent";
import { useMemo } from "react";
import { Milestone } from "../../proto/typescript/pb_out/main";

type Props = {
lifeEvent: Milestone;
updateLifeEvent: (newLifeEvent: Milestone) => void;
};

const EditingCareerEvent = ({ lifeEvent, updateLifeEvent }: Props) => {
const {
gridRow,
term,
editingState,
handleMouseDownSlide,
handleMouseDownExpansion,
} = useEditingCareerEvent({ lifeEvent, updateLifeEvent });

const cursorStyle = useMemo(() => {
switch (editingState) {
case "grabbing":
return "cursor-grabbing";
case "sliding":
return "cursor-row-resize";
case "none":
return "cursor-grab";
default:
return "";
}
}, [editingState]);

return (
<div
className={`bg-pink-500 col-start-2 col-end-3 select-none relative ${cursorStyle}`}
style={{ gridRow: `${gridRow.start}/${gridRow.end}` }}
onMouseDown={handleMouseDownSlide}
>
<p>{`${term.start.year}${term.start.month}月 ~ ${term.end.year}${term.end.month}月`}</p>
<p>{lifeEvent.title}</p>
<p>{lifeEvent.content}</p>
<div
className={`w-full h-5 absolute bottom-0 ${
editingState === "grabbing" ? "cursor-grabbing" : "cursor-row-resize"
}`}
onMouseDown={handleMouseDownExpansion}
>
{" "}
</div>
</div>
);
};

export default EditingCareerEvent;
43 changes: 43 additions & 0 deletions src/components/atoms/DetailModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react'


type Props = {
setIsModalOpen: (isModalOpen: boolean) => void;
title: string;
description: string;
}

const DetailModal = ({ setIsModalOpen, title, description }: Props) => {

const styles = {
modal: {
wallpaper: 'fixed top-0 left-0 w-full h-full bg-black bg-opacity-50 z-50',
modalBox: 'fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white w-11/12 md:w-1/2 h-1/2 rounded-3xl shadow-lg',
textBox: 'flex flex-col items-center justify-around w-full h-full px-12',
},
text: {
title: 'w-full text-2xl text-left ',
description: 'w-full text-lg h-60',
},
button: 'bg-blue-300 rounded-full w-16 h-8 flex justify-center items-center'
}


const CloseModal = () => setIsModalOpen(false)

return (
<>
<div className={styles.modal.wallpaper}>
<div className={styles.modal.modalBox}>
<div className={styles.modal.textBox}>
<h1 className={styles.text.title}>{title}</h1>
<p className={styles.text.description}>{description}</p>
<button className={styles.button} onClick={CloseModal}>Close</button>
</div>
</div>
</div>
</>
)
}

export default DetailModal
11 changes: 11 additions & 0 deletions src/components/atoms/Line.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react'

type Props = {}

const styles = {
boxing: 'w-1/2 md:h-24 h-12 border-l-4'
}

const Line = (props: Props) => (<div className={styles.boxing}></div>)

export default Line
44 changes: 44 additions & 0 deletions src/components/atoms/MileStoneContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react'
import { useState } from 'react'
import MileStoneTitle from './MileStoneTitle'
import MileStoneDescription from './MileStoneDescription'
import DetailModal from './DetailModal'

type Props = {
title: string
description: string
}

const MileStoneContent = ({ title, description }: Props) => {
// styles (IMO: No strict typing needed.)
const styles = {
sizing: 'w-11/12 h-full',
boxing: 'ml-2 md:p-4 md:pt-6 pt-6 break-words ',
text: 'whitespace-pre-line',
color: 'bg-gray-300',
border: 'rounded-lg'
}

// State
// TODO: implement custom hook
const [isModalOpen, setIsModalOpen] = useState<boolean>(false)
const openModal = () => setIsModalOpen(true)

// UI
return (
<div className={`${styles.sizing} ${styles.boxing} ${styles.text} ${styles.color} ${styles.border}`}>
<MileStoneTitle title={title} />

<MileStoneDescription
modal={<DetailModal setIsModalOpen={setIsModalOpen}
description={description}
title={title}/>}
isModalOpen={isModalOpen}
openModal={openModal}
description={description}
/>
</div>
)
}

export default MileStoneContent
Loading

0 comments on commit f45982b

Please sign in to comment.