From ae6b7a218c2f44c064b5fbee246535f719dff6e3 Mon Sep 17 00:00:00 2001 From: morifuji Date: Sat, 24 Feb 2024 23:18:47 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=97=A5=E4=BB=98=E3=82=92=E5=A4=89?= =?UTF-8?q?=E6=9B=B4=E5=8F=AF=E8=83=BD=E3=81=AB=E3=83=BB=E6=97=A5=E4=BB=98?= =?UTF-8?q?=E3=81=AE=E7=9B=B8=E5=AF=BE=E8=A1=A8=E7=A4=BA=E3=82=92=E3=82=8F?= =?UTF-8?q?=E3=81=8B=E3=82=8A=E3=82=84=E3=81=99=E3=81=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/ftft/ftft.controller.ts | 2 ++ backend/src/ftft/ftft.service.ts | 3 +- .../linelogin/linelogin.servuce.ts | 5 +++ frontend/src/FtftForm.tsx | 31 +++++++++++++--- frontend/src/FtftList.tsx | 35 +++++++++++++++++-- frontend/src/Home.tsx | 12 +++---- frontend/src/LineLogin.tsx | 12 ++----- frontend/src/Login.tsx | 2 +- frontend/src/Setting.tsx | 28 +++++++++++---- frontend/src/main.tsx | 26 +++++++++----- 10 files changed, 116 insertions(+), 40 deletions(-) diff --git a/backend/src/ftft/ftft.controller.ts b/backend/src/ftft/ftft.controller.ts index ccd55e9..bfa0319 100644 --- a/backend/src/ftft/ftft.controller.ts +++ b/backend/src/ftft/ftft.controller.ts @@ -38,6 +38,7 @@ export class FtftController { lng: z.number(), }) .optional(), + doneAt: z.string().datetime({ offset: true }).optional(), }) .parse(_body); return this.ftftService.createFtft({ @@ -47,6 +48,7 @@ export class FtftController { fileUrls: body.fileUrls, emoji: body.emoji, location: body.location, + doneAt: body.doneAt !== undefined ? new Date(body.doneAt) : undefined, }, }); } diff --git a/backend/src/ftft/ftft.service.ts b/backend/src/ftft/ftft.service.ts index f1c0042..9065c1a 100644 --- a/backend/src/ftft/ftft.service.ts +++ b/backend/src/ftft/ftft.service.ts @@ -26,6 +26,7 @@ export class FtftService { fileUrls: string[]; emoji?: string; location?: { lat: number; lng: number }; + doneAt?: Date; }; }) { const fileKeyList = ftft.fileUrls.map((fileUrl) => fileUrl.split('.amazonaws.com/')[1].split('?')[0]); @@ -36,7 +37,7 @@ export class FtftService { location: ftft.location, fileKeyList, id: randomUUID(), - createdAt: new Date().toISOString(), + createdAt: (ftft.doneAt || new Date()).toISOString(), }); this.dynamoDb.createItem({ diff --git a/backend/src/sociallogin/linelogin/linelogin.servuce.ts b/backend/src/sociallogin/linelogin/linelogin.servuce.ts index b3aac39..eafac0b 100644 --- a/backend/src/sociallogin/linelogin/linelogin.servuce.ts +++ b/backend/src/sociallogin/linelogin/linelogin.servuce.ts @@ -54,6 +54,11 @@ export class LineLoginService { .post<{ sub: string }>('https://api.line.me/oauth2/v2.1/verify', params) .then((response) => { return response.data.sub; + }) + .catch((error) => { + console.error('IDトークンの検証に失敗しました'); + console.error(error.response.data); + throw error; }); const lineUser = await this.userService.createLineUser(lineUserId); diff --git a/frontend/src/FtftForm.tsx b/frontend/src/FtftForm.tsx index 7e2e38b..8810fd7 100644 --- a/frontend/src/FtftForm.tsx +++ b/frontend/src/FtftForm.tsx @@ -1,16 +1,19 @@ import { ChangeEvent, useState } from 'react' import './App.css' import { Box, Button, IconButton, Input, Textarea } from "@chakra-ui/react" -import { AttachmentIcon, ChatIcon } from "@chakra-ui/icons" +import { AttachmentIcon, ChatIcon, TimeIcon } from "@chakra-ui/icons" import { API_BASE_URL } from './apiClient' import { useAuthorization } from './useAuthorization' import EmojiPicker from 'emoji-picker-react' import PinIcon from "./assets/pin-48.svg" +import { format } from 'date-fns' -export const FtftForm = ({ onSaveFtft }: { onSaveFtft: (ftft: { content: string, fileUrls: string[], emoji?: string, location?: { lat: number, lng: number } }) => Promise }) => { +export const FtftForm = ({ onSaveFtft }: { onSaveFtft: (ftft: { content: string, fileUrls: string[], emoji?: string, location?: { lat: number, lng: number }, doneAt?: Date }) => Promise }) => { const [content, setContent] = useState("") const [files, setFiles] = useState([]) const [emoji, setEmoji] = useState(undefined) + const [doneAt, setDoneAt] = useState(undefined) + const [isDisplayEmojiPicker, setIsDisplayEmojiPicker] = useState(false) const authorization = useAuthorization() @@ -63,6 +66,26 @@ export const FtftForm = ({ onSaveFtft }: { onSaveFtft: (ftft: { content: string, : {emoji}} onClick={() => setIsDisplayEmojiPicker(!isDisplayEmojiPicker)} /> + + + { + console.log(e.currentTarget.value) + if (!e.currentTarget.value) { + setDoneAt(undefined) + } else + setDoneAt(new Date(e.currentTarget.value)) + }}/> + + {doneAt === undefined ? } /> + : } + + : 📍} onClick={() => { if (location !== undefined) { setLocation(undefined) @@ -79,7 +102,6 @@ export const FtftForm = ({ onSaveFtft }: { onSaveFtft: (ftft: { content: string, ) => { - console.log(event.target.files) if (event.target.files && event.target.files?.length >= 1) { setFiles(files.concat(...event.target.files)) } @@ -106,12 +128,13 @@ export const FtftForm = ({ onSaveFtft }: { onSaveFtft: (ftft: { content: string, setIsLoading(true) try { const fileUrls = await uploadFile() - await onSaveFtft({ content, fileUrls, emoji, location }) + await onSaveFtft({ content, fileUrls, emoji, location, doneAt }) setLocation(undefined) setFiles([]) setContent("") setEmoji(undefined) + setDoneAt(undefined) } finally { setIsLoading(false) diff --git a/frontend/src/FtftList.tsx b/frontend/src/FtftList.tsx index 9c2b7ab..a841a6f 100644 --- a/frontend/src/FtftList.tsx +++ b/frontend/src/FtftList.tsx @@ -3,8 +3,7 @@ import { IconButton, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFoot import './App.css' import { Box, Button, Divider, Text } from "@chakra-ui/react" import { useSuspenseQuery } from '@tanstack/react-query' -import { format, formatRelative, parseISO } from 'date-fns' -import { ja } from 'date-fns/locale' +import { differenceInDays, differenceInHours, differenceInMinutes, differenceInMonths, differenceInWeeks, differenceInYears, format, parseISO } from 'date-fns' import { useAuthorization } from './useAuthorization' import { API_BASE_URL } from './apiClient' import 'react-calendar/dist/Calendar.css'; @@ -129,8 +128,38 @@ export const FtftList = () => { const CreatedAtLabel = memo(({ createdAt }: { createdAt: Date }) => { const [isRelative, setIsRelative] = useState(true) + + const formatRelative = (date1: Date, date2: Date): string => { + if (differenceInMinutes(date1, date2) < 10) { + return "さっき" + } + + if (differenceInMinutes(date1, date2) < 60) { + return differenceInMinutes(date1, date2) + "分前" + } + + if (differenceInHours(date1, date2) < 24) { + return differenceInHours(date1, date2) + "時間前" + } + + if (differenceInDays(date1, date2) < 7) { + return differenceInDays(date1, date2) + "日前" + } + + if (differenceInWeeks(date1, date2) < 5) { + return differenceInWeeks(date1, date2) + "週間前" + } + + if (differenceInMonths(date1, date2) < 12) { + return differenceInMonths(date1, date2) + "ヶ月前" + } + + return differenceInYears(date1, date2) + "年前" + + } + return setIsRelative(!isRelative)}>{ - isRelative ? formatRelative(createdAt, new Date(), { locale: ja }) : format(createdAt, "yyyy/MM/dd HH:mm:ss") + isRelative ? formatRelative(new Date(), createdAt) : format(createdAt, "yyyy/MM/dd HH:mm:ss") } }) diff --git a/frontend/src/Home.tsx b/frontend/src/Home.tsx index dc0ff18..cbee81e 100644 --- a/frontend/src/Home.tsx +++ b/frontend/src/Home.tsx @@ -18,7 +18,7 @@ export const Home = () => { const toast = useToast() - const saveFtft = async ({content, fileUrls, emoji, location}: {content: string, fileUrls: string[], emoji?: string, location?: {lat: number, lng: number}}) => { + const saveFtft = async ({content, fileUrls, emoji, location, doneAt}: {content: string, fileUrls: string[], emoji?: string, location?: {lat: number, lng: number}, doneAt?: Date}) => { await fetch(API_BASE_URL + '/ftft', { method: "POST", headers: { @@ -29,21 +29,21 @@ export const Home = () => { title: content, fileUrls, emoji, - location + location, + doneAt }) }).then(res=>{ - console.log(res.status) if (res.status !== 201) throw new Error("送信できませんでした") - const message = `${content}${emoji ? `\n${emoji}` : ''}\n\n-------------\n\nFTFTであなたの"はじめて"を記録しよう✍️\n` + const message = `${content}${emoji ? `\n${emoji}` : ''}\n\n-------------\n\nFTFTであなたの"はじめて"を記録しよう✍️ #FTFT-app\n` toast({ position: 'bottom', title: "記録しました✍️", description:

友達に - LINE VOOM + LINE VOOM や - X + X で共有しよう🥰

}) diff --git a/frontend/src/LineLogin.tsx b/frontend/src/LineLogin.tsx index 2f1882f..79ba10c 100644 --- a/frontend/src/LineLogin.tsx +++ b/frontend/src/LineLogin.tsx @@ -26,6 +26,8 @@ export const LineLogin = () => { const idToken = liff.getIDToken() + localStorage.clear() + const response = await fetch(API_BASE_URL + '/social-login/line/liff', { method: "POST", headers: { @@ -60,15 +62,7 @@ export const LineLogin = () => { return } - alert("エラーが発生しました\nSafariもしくはChromeで開いてください") - toast({ - position: 'bottom', - status: "error", - title: "エラーが発生しました", - description: "SafariもしくはChromeで開いてください" - }) - - navigate("/login") + liff.login() }) }, []) diff --git a/frontend/src/Login.tsx b/frontend/src/Login.tsx index 53cd5de..222e028 100644 --- a/frontend/src/Login.tsx +++ b/frontend/src/Login.tsx @@ -70,7 +70,7 @@ export const Login = () => { await liff.init({ liffId: "2003019183-014OmGVB" }) - liff.login({redirectUri: window.location.origin + "/line-login"}) + liff.login() }}>LINEでログイン diff --git a/frontend/src/Setting.tsx b/frontend/src/Setting.tsx index c5c7158..8242b97 100644 --- a/frontend/src/Setting.tsx +++ b/frontend/src/Setting.tsx @@ -1,9 +1,10 @@ import { TimeIcon } from '@chakra-ui/icons'; import './App.css' -import { Box, Button, Container, IconButton } from "@chakra-ui/react" +import { Box, Button, Container, IconButton, useToast } from "@chakra-ui/react" import { Link, useNavigate } from 'react-router-dom'; export const Setting = () => { + const toast = useToast() const navigate = useNavigate() @@ -16,12 +17,25 @@ export const Setting = () => { />
- + + + + + } diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index ed8c216..175801a 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,16 +1,24 @@ import ReactDOM from 'react-dom/client' import App from './App.tsx' import './index.css' -// import eruda from "eruda" +import eruda from "eruda" -// if (window.location.origin === "https://d3ozb6rt05ntqw.cloudfront.net") { - // const el = document.createElement('div'); - // document.body.appendChild(el); - - // eruda.init({ - // container: el, - // }); -// } +if (window.location.origin.includes("5173")) { +const el = document.createElement('div'); +document.body.appendChild(el); + +eruda.init({ + container: el, +}); +} + + +const searchParams = new URLSearchParams(window.location.search) +const ftftAuthorization = searchParams.get("ftftAuthorization") +if (ftftAuthorization) { + localStorage.setItem("authorization", ftftAuthorization) + window.location.href = window.location.origin +window.location.pathname +} ReactDOM.createRoot(document.getElementById('root')!).render(