diff --git a/packages/store-client/.env.development b/packages/store-client/.env.development new file mode 100644 index 0000000..1ef76db --- /dev/null +++ b/packages/store-client/.env.development @@ -0,0 +1,5 @@ +SITE_URL=https://store.coldsurf.io +GOOGLE_OAUTH_CLIENT_ID= +GOOGLE_OAUTH_CLIENT_SECRET= +AUTH_SECRET= +BASE_URL=http://localhost:8000/api/v1/ \ No newline at end of file diff --git a/packages/store-client/.env.production b/packages/store-client/.env.production new file mode 100644 index 0000000..1c455c1 --- /dev/null +++ b/packages/store-client/.env.production @@ -0,0 +1,5 @@ +SITE_URL=https://store.coldsurf.io +GOOGLE_OAUTH_CLIENT_ID= +GOOGLE_OAUTH_CLIENT_SECRET= +AUTH_SECRET= +BASE_URL=https://api.store.coldsurf.io/api/v1/ \ No newline at end of file diff --git a/packages/store-client/.eslintrc b/packages/store-client/.eslintrc new file mode 100644 index 0000000..ac72403 --- /dev/null +++ b/packages/store-client/.eslintrc @@ -0,0 +1,12 @@ +{ + "extends": [ + "coldsurfers", // for nodejs-typescript, or 'coldsurfers/nodejs-typescript' + "coldsurfers/react-typescript" // for react-typescript + ], + "plugins": ["@tanstack/query"], + "rules": { + "import/extensions": "off", + "import/no-unresolved": "off", + "no-undef": "off" + } +} \ No newline at end of file diff --git a/packages/store-client/.gitignore b/packages/store-client/.gitignore new file mode 100644 index 0000000..8d574ff --- /dev/null +++ b/packages/store-client/.gitignore @@ -0,0 +1,38 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env +# .env.production + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/packages/store-client/.prettierrc.json b/packages/store-client/.prettierrc.json new file mode 100644 index 0000000..fbe0e55 --- /dev/null +++ b/packages/store-client/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true +} \ No newline at end of file diff --git a/packages/store-client/README.md b/packages/store-client/README.md new file mode 100644 index 0000000..bcf7c7a --- /dev/null +++ b/packages/store-client/README.md @@ -0,0 +1,3 @@ +Hello, this repo was moved to `https://github.com/coldsurfers/store.coldsurf.io`. + +Thanks! \ No newline at end of file diff --git a/packages/store-client/app/api/auth/[...nextauth]/route.ts b/packages/store-client/app/api/auth/[...nextauth]/route.ts new file mode 100644 index 0000000..28bc4dd --- /dev/null +++ b/packages/store-client/app/api/auth/[...nextauth]/route.ts @@ -0,0 +1,3 @@ +import { handlers } from '../../../../libs/auth' + +export const { GET, POST } = handlers diff --git a/packages/store-client/app/favicon.ico b/packages/store-client/app/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/packages/store-client/app/favicon.ico differ diff --git a/packages/store-client/app/layout.tsx b/packages/store-client/app/layout.tsx new file mode 100644 index 0000000..953c837 --- /dev/null +++ b/packages/store-client/app/layout.tsx @@ -0,0 +1,33 @@ +import type { Metadata } from 'next' +import { Inter } from 'next/font/google' +import { ReactNode } from 'react' +import LayoutWrapper from '@/components/LayoutWrapper' +import { MODAL_PORTAL_ID } from '@/libs/constants' +import { auth } from '@/libs/auth' +import GlobalStyle from '@/components/GlobalStyle' + +const inter = Inter({ subsets: ['latin'] }) + +export const metadata: Metadata = { + title: 'Store | ColdSurf', +} + +export default async function RootLayout({ + children, +}: { + children: ReactNode +}) { + const session = await auth() + + return ( + + + + + + {children} +
+ + + ) +} diff --git a/packages/store-client/app/page.tsx b/packages/store-client/app/page.tsx new file mode 100644 index 0000000..20d0f19 --- /dev/null +++ b/packages/store-client/app/page.tsx @@ -0,0 +1,87 @@ +import { queryList } from '@coldsurfers/notion-utils' +import { + PageObjectResponse, + // PartialPageObjectResponse, + // RichTextItemResponse, + // TextRichTextItemResponse, +} from '@notionhq/client/build/src/api-endpoints' +import Link from 'next/link' +import { cache } from 'react' + +const getAllPosts = cache( + async () => + // eslint-disable-next-line no-return-await + await queryList({ + platform: 'store', + direction: 'descending', + timestamp: 'created_time', + }) +) + +// type A = PageObjectResponse + +export async function getInternalPosts( + options = { + status: 'Published', + } +) { + const { status = 'Published' } = options + try { + const rawPosts = (await getAllPosts()) as PageObjectResponse[] + const posts = rawPosts.map((post) => { + const createdTime = new Date(post.created_time) + const lastEditedTime = new Date(post.last_edited_time) + const { properties } = post + const slugProperty = properties.Slug + const nameProperty = properties.Name + console.log(nameProperty) + + let slug: string | undefined = '' + let title: string | undefined = '' + + if (slugProperty.type === 'rich_text') { + slug = slugProperty.rich_text.at(0)?.plain_text + // console.log(slugProperty.rich_text.at(0)?.plain_text) + } + if (nameProperty.type === 'title') { + title = nameProperty.title.at(0)?.plain_text + // console.log(slugProperty.rich_text.at(0)?.plain_text) + } + // console.log(post.properties, slugProperty) + + // const title = post.properties?.Name?.title + // console.log(title) + // const postStatus = post.properties.Status.status.name + return { + id: post.id, + createdTime, + lastEditedTime, + dateLocale: createdTime.toLocaleString('en-US', { + month: 'short', + day: '2-digit', + year: 'numeric', + }), + slug, + title, + // status: postStatus, + } + }) + + return posts + + // return posts.filter((post) => post.status === status) + } catch (e) { + console.error(e) + return null + } +} + +export default async function Home() { + const posts = await getInternalPosts() + + return posts?.map((post) => ( + +

{post.title}

+ + )) +} diff --git a/packages/store-client/components/Button.tsx b/packages/store-client/components/Button.tsx new file mode 100644 index 0000000..7356788 --- /dev/null +++ b/packages/store-client/components/Button.tsx @@ -0,0 +1,21 @@ +/* eslint-disable no-undef */ +import styled from '@emotion/styled' +import { ButtonHTMLAttributes, DetailedHTMLProps } from 'react' + +export interface ButonProps + extends DetailedHTMLProps< + ButtonHTMLAttributes, + HTMLButtonElement + > {} + +const ButtonBase = styled.button` + border-radius: 14px; + padding: 0.5rem; + border: none; + font-size: 14px; + cursor: pointer; +` + +export default function Button(props: ButonProps) { + return +} diff --git a/packages/store-client/components/Footer.tsx b/packages/store-client/components/Footer.tsx new file mode 100644 index 0000000..4fc2f2e --- /dev/null +++ b/packages/store-client/components/Footer.tsx @@ -0,0 +1,17 @@ +'use client' + +import styled from '@emotion/styled' + +const Container = styled.div` + width: 100%; + height: 15rem; + padding: 1rem; +` + +export default function Footer() { + return ( + +
© coldsurf
+
+ ) +} diff --git a/packages/store-client/components/GlobalStyle.tsx b/packages/store-client/components/GlobalStyle.tsx new file mode 100644 index 0000000..a794179 --- /dev/null +++ b/packages/store-client/components/GlobalStyle.tsx @@ -0,0 +1,7 @@ +'use client' + +import { GlobalStyle } from '@coldsurfers/ocean-road' + +export default function AppGlobalStyle() { + return +} diff --git a/packages/store-client/components/Header.tsx b/packages/store-client/components/Header.tsx new file mode 100644 index 0000000..d09aa90 --- /dev/null +++ b/packages/store-client/components/Header.tsx @@ -0,0 +1,50 @@ +'use client' + +import styled from '@emotion/styled' +import Link from 'next/link' +import { signOut, useSession } from 'next-auth/react' +import { useCallback } from 'react' +import Button from './Button' +import { useLoginModalStore } from './LoginModal' + +const Container = styled.div` + width: 100%; + padding: 1rem; + display: flex; + align-items: center; +` + +const CompanyLogo = styled.h2` + font-weight: bold; +` + +const LoginButtonWrapper = styled(Button)` + margin-left: auto; +` + +export default function Header() { + const { open } = useLoginModalStore() + const { data: session } = useSession() + const isLoggedIn = !!session + const onClickLogout = useCallback(async () => { + await signOut() + }, []) + return ( + + + ColdSurf Store + + {isLoggedIn ? ( + Log Out + ) : ( + Log In + )} + + ) +} diff --git a/packages/store-client/components/Input.tsx b/packages/store-client/components/Input.tsx new file mode 100644 index 0000000..e9a2cfb --- /dev/null +++ b/packages/store-client/components/Input.tsx @@ -0,0 +1,14 @@ +/* eslint-disable no-undef */ +import { DetailedHTMLProps, InputHTMLAttributes, forwardRef } from 'react' + +export interface InputProps + extends DetailedHTMLProps< + InputHTMLAttributes, + HTMLInputElement + > {} + +const Input = forwardRef((props, ref) => ( + +)) + +export default Input diff --git a/packages/store-client/components/LayoutWrapper.tsx b/packages/store-client/components/LayoutWrapper.tsx new file mode 100644 index 0000000..24a4b1a --- /dev/null +++ b/packages/store-client/components/LayoutWrapper.tsx @@ -0,0 +1,45 @@ +'use client' + +import { PropsWithChildren } from 'react' +import styled from '@emotion/styled' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { SessionProvider } from 'next-auth/react' +import { Session } from 'next-auth/types' +import Header from './Header' +import Footer from './Footer' +import LoginModal from './LoginModal' + +const Container = styled.div` + display: flex; + flex-direction: column; + min-height: 100vh; + max-width: 960px; + margin-left: auto; + margin-right: auto; +` + +const ChildrenWrapper = styled.div` + flex: 1; +` + +export const queryClient = new QueryClient({}) + +export default async function LayoutWrapper({ + children, + session, +}: PropsWithChildren<{ + session?: Session | null +}>) { + return ( + + + +
+ {children} +