Skip to content

Commit

Permalink
feat(examples): add supabse with nextjs
Browse files Browse the repository at this point in the history
  • Loading branch information
alicanerdurmaz committed May 27, 2024
1 parent d6fba25 commit b468c9a
Show file tree
Hide file tree
Showing 39 changed files with 1,365 additions and 0 deletions.
36 changes: 36 additions & 0 deletions examples/with-nextjs-supabase/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 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

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
2 changes: 2 additions & 0 deletions examples/with-nextjs-supabase/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
legacy-peer-deps=true
strict-peer-dependencies=false
43 changes: 43 additions & 0 deletions examples/with-nextjs-supabase/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<div align="center" style="margin: 30px;">
<a href="https://refine.dev/">
<img alt="refine logo" src="https://refine.ams3.cdn.digitaloceanspaces.com/readme/refine-readme-banner.png">
</a>

</br>
</br>

<div align="center">
<a href="https://refine.dev">Home Page</a> |
<a href="https://discord.gg/refine">Discord</a> |
<a href="https://refine.dev/examples/">Examples</a> |
<a href="https://refine.dev/blog/">Blog</a> |
<a href="https://refine.dev/docs/">Documentation</a>
</div>
</div>

</br>
</br>

<div align="center"><strong>Build your <a href="https://reactjs.org/">React</a>-based CRUD applications, without constraints.</strong><br>An open source, headless web application framework developed with flexibility in mind.

<br />
<br />

[![Discord](https://img.shields.io/discord/837692625737613362.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/refine)
[![Twitter Follow](https://img.shields.io/twitter/follow/refine_dev?style=social)](https://twitter.com/refine_dev)

<a href="https://www.producthunt.com/posts/refine-3?utm_source=badge-top-post-badge&utm_medium=badge&utm_souce=badge-refine&#0045;3" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/top-post-badge.svg?post_id=362220&theme=light&period=daily" alt="refine - 100&#0037;&#0032;open&#0032;source&#0032;React&#0032;framework&#0032;to&#0032;build&#0032;web&#0032;apps&#0032;3x&#0032;faster | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>

</div>

## Try this example on your local

```bash
npm create refine-app@latest -- --example with-nextjs-supabase
```

## Try this example on CodeSandbox

<br/>

[![Open with-nextjs-supabase example from refine](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/embed/github/refinedev/refine/tree/master/examples/with-nextjs-supabase?view=preview&theme=dark&codemirror=1)
6 changes: 6 additions & 0 deletions examples/with-nextjs-supabase/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ["@refinedev/antd"],
};

export default nextConfig;
41 changes: 41 additions & 0 deletions examples/with-nextjs-supabase/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "with-nextjs-supabase",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "refine build",
"dev": "cross-env NODE_OPTIONS=--max_old_space_size=4096 refine dev",
"start:prod": "refine start"
},
"dependencies": {
"@ant-design/icons": "^5.0.1",
"@ant-design/nextjs-registry": "^1.0.0",
"@refinedev/antd": "^5.38.1",
"@refinedev/cli": "^2.16.31",
"@refinedev/core": "^4.49.2",
"@refinedev/devtools": "^1.2.1",
"@refinedev/kbar": "^1.3.10",
"@refinedev/nextjs-router": "^6.0.4",
"@refinedev/simple-rest": "^5.0.6",
"@supabase/ssr": "^0.3.0",
"antd": "5.16.5",
"cross-env": "^7.0.3",
"js-cookie": "^3.0.1",
"next": "^14.1.0",
"nookies": "^2.5.2",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@types/node": "^18.16.2",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@typescript-eslint/parser": "5.48.0",
"cross-env": "^7.0.3",
"eslint": "^8.24.0",
"typescript": "^5.4.2"
},
"engines": {
"node": ">=18.0.0"
}
}
Binary file added examples/with-nextjs-supabase/public/favicon.ico
Binary file not shown.
72 changes: 72 additions & 0 deletions examples/with-nextjs-supabase/src/app/blog-posts/create/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"use client";

import { Create, useForm, useSelect } from "@refinedev/antd";
import { Form, Input, Select } from "antd";

export default function BlogPostCreate() {
const { formProps, saveButtonProps } = useForm({});

const { selectProps: categorySelectProps } = useSelect({
resource: "categories",
});

return (
<Create saveButtonProps={saveButtonProps}>
<Form {...formProps} layout="vertical">
<Form.Item
label={"Title"}
name={["title"]}
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label={"Content"}
name="content"
rules={[
{
required: true,
},
]}
>
<Input.TextArea rows={5} />
</Form.Item>
<Form.Item
label={"Category"}
name={"categoryId"}
rules={[
{
required: true,
},
]}
>
<Select {...categorySelectProps} />
</Form.Item>
<Form.Item
label={"Status"}
name={["status"]}
initialValue={"draft"}
rules={[
{
required: true,
},
]}
>
<Select
defaultValue={"draft"}
options={[
{ value: "draft", label: "Draft" },
{ value: "published", label: "Published" },
{ value: "rejected", label: "Rejected" },
]}
style={{ width: 120 }}
/>
</Form.Item>
</Form>
</Create>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"use client";

import { Edit, useForm, useSelect } from "@refinedev/antd";
import { Form, Input, Select } from "antd";

export default function BlogPostEdit() {
const { formProps, saveButtonProps, queryResult } = useForm({
meta: {
select: "*, categories(id,title)",
},
});

const blogPostsData = queryResult?.data?.data;

const { selectProps: categorySelectProps } = useSelect({
resource: "categories",
defaultValue: blogPostsData?.categories?.id,
});

return (
<Edit saveButtonProps={saveButtonProps}>
<Form {...formProps} layout="vertical">
<Form.Item
label={"Title"}
name={["title"]}
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label={"Content"}
name="content"
rules={[
{
required: true,
},
]}
>
<Input.TextArea rows={5} />
</Form.Item>
<Form.Item
label={"Category"}
name={"categoryId"}
initialValue={formProps?.initialValues?.categories?.id}
rules={[
{
required: true,
},
]}
>
<Select {...categorySelectProps} />
</Form.Item>
<Form.Item
label={"Status"}
name={["status"]}
initialValue={"draft"}
rules={[
{
required: true,
},
]}
>
<Select
defaultValue={"draft"}
options={[
{ value: "draft", label: "Draft" },
{ value: "published", label: "Published" },
{ value: "rejected", label: "Rejected" },
]}
style={{ width: 120 }}
/>
</Form.Item>
</Form>
</Edit>
);
}
23 changes: 23 additions & 0 deletions examples/with-nextjs-supabase/src/app/blog-posts/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ThemedLayout } from "@components/themed-layout";
import { authProviderServer } from "@providers/auth-provider";
import { redirect } from "next/navigation";
import React from "react";

export default async function Layout({ children }: React.PropsWithChildren) {
const data = await getData();

if (!data.authenticated) {
return redirect(data?.redirectTo || "/login");
}

return <ThemedLayout>{children}</ThemedLayout>;
}

async function getData() {
const { authenticated, redirectTo } = await authProviderServer.check();

return {
authenticated,
redirectTo,
};
}
78 changes: 78 additions & 0 deletions examples/with-nextjs-supabase/src/app/blog-posts/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"use client";

import {
DateField,
DeleteButton,
EditButton,
List,
MarkdownField,
ShowButton,
useTable,
} from "@refinedev/antd";
import { BaseRecord, useMany } from "@refinedev/core";
import { Space, Table } from "antd";

export default function BlogPostList() {
const { tableProps } = useTable({
syncWithLocation: true,
meta: {
select: "*, categories(id,title)",
},
});

const { data: categoryData, isLoading: categoryIsLoading } = useMany({
resource: "categories",
ids:
tableProps?.dataSource
?.map((item) => item?.categories?.id)
.filter(Boolean) ?? [],
queryOptions: {
enabled: !!tableProps?.dataSource,
},
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title={"ID"} />
<Table.Column dataIndex="title" title={"Title"} />
<Table.Column
dataIndex="content"
title={"Content"}
render={(value: any) => {
if (!value) return "-";
return <MarkdownField value={value.slice(0, 80) + "..."} />;

Check failure on line 44 in examples/with-nextjs-supabase/src/app/blog-posts/page.tsx

View workflow job for this annotation

GitHub Actions / Lint (18.x)

Template literals are preferred over string concatenation.
}}
/>
<Table.Column
dataIndex={"categories"}
title={"Category"}
render={(value) =>
categoryIsLoading ? (
<>Loading...</>
) : (
categoryData?.data?.find((item) => item.id === value?.id)?.title
)
}
/>
<Table.Column dataIndex="status" title={"Status"} />
<Table.Column
dataIndex={["createdAt"]}
title={"Created at"}
render={(value: any) => <DateField value={value} />}
/>
<Table.Column
title={"Actions"}
dataIndex="actions"
render={(_, record: BaseRecord) => (
<Space>
<EditButton hideText size="small" recordItemId={record.id} />
<ShowButton hideText size="small" recordItemId={record.id} />
<DeleteButton hideText size="small" recordItemId={record.id} />
</Space>
)}
/>
</Table>
</List>
);
}
Loading

0 comments on commit b468c9a

Please sign in to comment.