58 | Nextjs Hasura Fullstack 59 |
60 |
61 | A boilerplate that uses{' '}
62 |
├── .vscode └── settings.json ├── README.md ├── TODO.md ├── app.json ├── generateKeys.js ├── hasura ├── .dockerignore ├── .gitignore ├── Dockerfile ├── config.yaml ├── docker-compose.yml ├── metadata │ ├── actions.graphql │ ├── actions.yaml │ ├── allow_list.yaml │ ├── cron_triggers.yaml │ ├── functions.yaml │ ├── query_collections.yaml │ ├── remote_schemas.yaml │ ├── tables.yaml │ └── version.yaml └── migrations │ ├── 1597498463371_create_table_public_users │ ├── down.sql │ └── up.sql │ ├── 1597498548202_create_table_public_accounts │ ├── down.sql │ └── up.sql │ ├── 1597498609423_create_table_public_sessions │ ├── down.sql │ └── up.sql │ ├── 1597498658823_create_table_public_verification_requests │ ├── down.sql │ └── up.sql │ ├── 1597498709972_create_table_public_feeds │ ├── down.sql │ └── up.sql │ ├── 1597498729906_set_fk_public_feeds_user_id │ ├── down.sql │ └── up.sql │ ├── 1597504190869_create_table_public_boards │ ├── down.sql │ └── up.sql │ ├── 1597505181237_create_table_public_boards_users │ ├── down.sql │ └── up.sql │ ├── 1597505238023_create_table_public_lists │ ├── down.sql │ └── up.sql │ ├── 1597505340738_create_table_public_cards │ ├── down.sql │ └── up.sql │ ├── 1597577533977_alter_table_public_lists_alter_column_position │ ├── down.sql │ └── up.sql │ ├── 1597577544193_alter_table_public_lists_drop_constraint_lists_position_key │ ├── down.sql │ └── up.sql │ ├── 1597577650903_alter_table_public_lists_alter_column_position │ ├── down.sql │ └── up.sql │ ├── 1597577665522_alter_table_public_cards_alter_column_position │ ├── down.sql │ └── up.sql │ ├── 1597601412648_alter_table_public_lists_alter_column_position │ ├── down.sql │ └── up.sql │ ├── 1597601429537_alter_table_public_lists_add_unique_board_id_position │ ├── down.sql │ └── up.sql │ ├── 1599496540352_alter_table_public_boards_add_column_icon │ ├── down.sql │ └── up.sql │ ├── 1599632432195_alter_table_public_lists_drop_constraint_lists_board_id_position_key │ ├── down.sql │ └── up.sql │ ├── 1599670620301_alter_table_public_lists_alter_column_position │ ├── down.sql │ └── up.sql │ ├── 1599670653341_alter_table_public_cards_alter_column_position │ ├── down.sql │ └── up.sql │ ├── 1599915366833_set_fk_public_cards_list_id │ ├── down.sql │ └── up.sql │ ├── 1599915561792_set_fk_public_cards_board_id │ ├── down.sql │ └── up.sql │ └── 1599915623950_set_fk_public_lists_board_id │ ├── down.sql │ └── up.sql ├── heroku.yml ├── license.md └── nextjs ├── .babelrc ├── .env.example ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .prettierignore ├── .prettierrc ├── codegen.yml ├── graphql.schema.json ├── next-env.d.ts ├── next.config.js ├── package.json ├── postcss.config.js ├── public └── images │ ├── bug_fixed.svg │ ├── favicon.ico │ └── logo.png ├── schema.prisma ├── src ├── components │ ├── AccessDeniedIndicator.tsx │ ├── AddInput.tsx │ ├── CustomLink.tsx │ ├── ItemLink.tsx │ ├── Loader.tsx │ ├── icons │ │ ├── BalanceIcon.tsx │ │ ├── ChartIcon.tsx │ │ ├── ClientIcon.tsx │ │ ├── ContactIcon.tsx │ │ ├── DashboardIcon.tsx │ │ ├── FormIcon.tsx │ │ ├── HamburgerIcon.tsx │ │ ├── Logo.tsx │ │ ├── LogoutIcon.tsx │ │ ├── MailIcon.tsx │ │ ├── MoonIcon.tsx │ │ ├── NotificationIcon.tsx │ │ ├── ProfileIcon.tsx │ │ ├── SaleIcon.tsx │ │ ├── SearchIcon.tsx │ │ ├── SettingsIcon.tsx │ │ ├── StarIcon.tsx │ │ └── SunIcon.tsx │ └── pages │ │ ├── account │ │ ├── graphql │ │ │ ├── UpdateUser.graphql │ │ │ └── User.graphql │ │ └── index.tsx │ │ ├── boards │ │ ├── board │ │ │ ├── boardUtils.ts │ │ │ ├── graphql │ │ │ │ └── BoardQuery.graphql │ │ │ └── index.tsx │ │ ├── card │ │ │ ├── NewCard.tsx │ │ │ ├── graphql │ │ │ │ ├── CardFragment.graphql │ │ │ │ ├── DeleteCard.graphql │ │ │ │ ├── InsertCard.graphql │ │ │ │ ├── MoveCard.graphql │ │ │ │ └── UpdateCard.graphql │ │ │ └── index.tsx │ │ ├── graphql │ │ │ ├── BoardFragment.graphql │ │ │ ├── Boards.graphql │ │ │ ├── DeleteBoard.graphql │ │ │ └── InsertBoard.graphql │ │ ├── index.tsx │ │ └── list │ │ │ ├── ActionDropdown.tsx │ │ │ ├── ListHeader.tsx │ │ │ ├── NewList.tsx │ │ │ ├── graphql │ │ │ ├── DeleteList.graphql │ │ │ ├── InsertList.graphql │ │ │ ├── ListFragment.graphql │ │ │ └── UpdateList.graphql │ │ │ └── index.tsx │ │ ├── error │ │ └── index.tsx │ │ ├── feeds │ │ ├── AddNewFeedForm.tsx │ │ ├── feed.tsx │ │ ├── graphql │ │ │ ├── FeedFragment.graphql │ │ │ ├── Feeds.graphql │ │ │ └── InsertFeed.graphql │ │ └── index.tsx │ │ └── index │ │ └── Book.tsx ├── generated │ └── graphql.tsx ├── layouts │ ├── BoardLayout.tsx │ ├── MainLayout.tsx │ └── components │ │ ├── Footer.tsx │ │ ├── Header.tsx │ │ └── main │ │ ├── Sidebar.tsx │ │ └── SidebarMobile.tsx ├── lib │ ├── apolloClient.tsx │ └── cache.ts ├── pages │ ├── 404.tsx │ ├── _app.tsx │ ├── _document.tsx │ ├── _error.tsx │ ├── account.tsx │ ├── api │ │ └── auth │ │ │ └── [...nextauth].ts │ ├── boards │ │ ├── [boardId].tsx │ │ └── index.tsx │ ├── feeds.tsx │ └── index.tsx ├── styles │ ├── bar-of-progress.css │ └── tailwind.css ├── types │ ├── page.ts │ ├── session.ts │ ├── token.ts │ └── user.ts ├── utils │ ├── createCtx.ts │ ├── index.ts │ └── timeFromNow.tsx └── zustands │ └── boards.ts ├── tailwind.config.js ├── tsconfig.json ├── vendor.d.ts └── yarn.lock /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.watcherExclude": { 3 | "**/.git/objects/**": true, 4 | "**/.git/subtree-cache/**": true, 5 | "**/.hg/store/**": true 6 | } 7 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## (Unmaintained status - Take it as a learning resource) 2 |
3 |
4 |
9 |
10 |
11 |
12 |
NextHasura
61 |Error: {fetchUserError.message}
77 | } 78 | 79 | return ( 80 |{card.description}
83 |25 | {statusCode 26 | ? `An error ${statusCode} occurred on server` 27 | : 'An error occurred on client'} 28 |
29 |{feed.user.name}
22 |{timeFromNow(feed.created_at)}
25 |{feed.body}
31 |25 | 37 | 6km from city center 38 |
39 |41 | from $35 a night 42 |
43 |8 | Copyright © 2020 9 | 10 | 11 | @sondh0127 12 | 13 | 14 |
15 |
61 | A boilerplate that uses{' '}
62 |
= NextPage
& { 5 | getLayout?: (component: JSX.Element) => JSX.Element 6 | } 7 | 8 | export type AppPropsWithLayout
= AppProps & { 9 | Component: NextPageWithLayout
10 | } 11 | -------------------------------------------------------------------------------- /nextjs/src/types/session.ts: -------------------------------------------------------------------------------- 1 | import { Session as AuthSession } from 'next-auth/client' 2 | 3 | export default interface Session extends AuthSession { 4 | id?: number 5 | token?: string 6 | } 7 | 8 | export type SessionProp = { 9 | session: Session | null 10 | } 11 | -------------------------------------------------------------------------------- /nextjs/src/types/token.ts: -------------------------------------------------------------------------------- 1 | export default interface Token { 2 | id: number 3 | email: string 4 | name: string 5 | picture: string 6 | } 7 | -------------------------------------------------------------------------------- /nextjs/src/types/user.ts: -------------------------------------------------------------------------------- 1 | export default interface User { 2 | id: number 3 | name: string 4 | image: string 5 | email: string 6 | } 7 | -------------------------------------------------------------------------------- /nextjs/src/utils/createCtx.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export const createCtx = | null>() => { 4 | const ctx = React.createContext(undefined) 5 | 6 | const useCtx = () => { 7 | const c = React.useContext(ctx) 8 | if (c === undefined) 9 | throw new Error('useCtx must be inside a Provider with a value') 10 | return c 11 | } 12 | 13 | return [useCtx, ctx.Provider] as const // 'as const' makes TypeScript infer a tuple 14 | } 15 | -------------------------------------------------------------------------------- /nextjs/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './timeFromNow' 2 | -------------------------------------------------------------------------------- /nextjs/src/utils/timeFromNow.tsx: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs' 2 | import relativeTime from 'dayjs/plugin/relativeTime' 3 | 4 | dayjs.extend(relativeTime) 5 | 6 | export const timeFromNow = (time: string): string => { 7 | return dayjs(time).fromNow() 8 | } 9 | -------------------------------------------------------------------------------- /nextjs/src/zustands/boards.ts: -------------------------------------------------------------------------------- 1 | import create from 'zustand' 2 | 3 | export const useLastPositionNumber = create<{ 4 | lastPosition: number 5 | setLastPosition: (lastPosition: number) => void 6 | }>((set) => ({ 7 | lastPosition: 0, 8 | setLastPosition: (lastPosition) => set(() => ({ lastPosition })), 9 | })) 10 | -------------------------------------------------------------------------------- /nextjs/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | const defaultTheme = require('tailwindcss/defaultTheme') 3 | const { resolveConfig } = require('@retail-ui/core') 4 | 5 | module.exports = resolveConfig({ 6 | experimental: { 7 | applyComplexClasses: true, 8 | uniformColorPalette: true, 9 | extendedSpacingScale: true, 10 | defaultLineHeights: true, 11 | extendedFontSizeScale: true, 12 | removeDeprecatedGapUtilities: true, 13 | purgeLayersByDefault: true, 14 | }, 15 | purge: ['./src/**/*.{js,ts,jsx,tsx}'], 16 | theme: { 17 | extend: { 18 | fontFamily: { 19 | sans: ['Inter', ...defaultTheme.fontFamily.sans], 20 | }, 21 | }, 22 | }, 23 | variants: { 24 | display: ['responsive', 'dark', 'last', 'group-hover'], 25 | }, 26 | plugins: [require('@tailwindcss/ui')], 27 | }) 28 | -------------------------------------------------------------------------------- /nextjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "alwaysStrict": true, 7 | "skipLibCheck": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "esModuleInterop": true, 13 | "module": "esnext", 14 | "moduleResolution": "node", 15 | "resolveJsonModule": true, 16 | "isolatedModules": true, 17 | "jsx": "preserve", 18 | "baseUrl": ".", 19 | "paths": { 20 | "@/*": ["src/*"] 21 | } 22 | }, 23 | "exclude": ["node_modules", "tailwind.config.js"], 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"] 25 | } 26 | -------------------------------------------------------------------------------- /nextjs/vendor.d.ts: -------------------------------------------------------------------------------- 1 | // declare module 'next-auth/client' 2 | // declare module 'next-auth' 3 | // declare module 'next-auth/providers' 4 | --------------------------------------------------------------------------------