DEV Community

mhrrmk for Refine

Posted on • Edited on • Originally published at refine.dev

9 6

Let's build an app to manage your hackathons with refine

We'll be building a demo app to manage hackathons with refine. We'll be able to create new hackathons, new project entries for a hackathon and criterias for a hackathon.

Alt Text

We'll use supabase as the backend service. refine comes with a builtin data provider for supabase thus it's very easy to create crud pages.

Creating tables

Our app will have these tables in supabase

  • criterias
  • hackathons
  • hackathoners
  • projects
  • projectscores

These are reflected in our app as

export type HackathonerType = {
  id: string;
  name: string;
};

export type HackathonType = {
  id: string;
  start: string;
  end: string;
  name: string;
};

export type ProjectType = {
  id: string;
  name: string;
  description: string;
  url: string;
  hackathon_id: string;
  hackathoner_id: string;
};

export type CriteriaType = {
  id: string;
  name: string;
  hackathon_id: string;
};

export type ProjectScoreType = {
  project_id: string;
  criteria_id: string;
  score: string;
};

Enter fullscreen mode Exit fullscreen mode

Craeting CRUD pages

Creating crud pages is as easy like this:

List page:

import {
  List,
  Table,
  useTable,
  Space,
  ShowButton,
  EditButton,
  TextField,
} from "@pankod/refine";

import dayjs from "dayjs";

import { HackathonType } from "interfaces";

export const HackathonsList: React.FC = () => {
  const { tableProps } = useTable<HackathonType>();

  return (
    <List>
      <Table {...tableProps} rowKey="id">
        <Table.Column dataIndex="id" title="ID" />
        <Table.Column dataIndex="name" title="Name" />
        <Table.Column
          dataIndex="start"
          title="Starts"
          render={(value) => (
            <TextField value={dayjs(value).format("DD/MMMM dddd")} />
          )}
        />
        <Table.Column
          dataIndex="end"
          title="Ends"
          render={(value) => (
            <TextField value={dayjs(value).format("DD/MMMM dddd")} />
          )}
        />
        <Table.Column
          title="Actions"
          dataIndex="actions"
          render={(_text, record: HackathonType): React.ReactNode => {
            return (
              <Space>
                <ShowButton size="small" recordItemId={record.id} hideText />
                <EditButton size="small" recordItemId={record.id} hideText />
              </Space>
            );
          }}
        />
      </Table>
    </List>
  );
};

Enter fullscreen mode Exit fullscreen mode

Create page:

import { Create, Form, Input, useForm, DatePicker } from "@pankod/refine";

import { HackathonType } from "interfaces";

export const HackathonsCreate: React.FC = () => {
  const { formProps, saveButtonProps } = useForm<HackathonType>();

  return (
    <Create saveButtonProps={saveButtonProps}>
      <Form {...formProps} layout="vertical">
        <Form.Item label="Name" name="name">
          <Input />
        </Form.Item>
        <Form.Item label="Name" name="start">
          <DatePicker />
        </Form.Item>
        <Form.Item label="Name" name="end">
          <DatePicker />
        </Form.Item>
      </Form>
    </Create>
  );
};
Enter fullscreen mode Exit fullscreen mode

Then use these pages as the corresponding crud component for the hackathon resource:

import { Refine, Resource } from "@pankod/refine";

import "@pankod/refine/dist/styles.min.css";
import { dataProvider } from "@pankod/refine-supabase";
import { supabaseClient } from "utility";
import {
  HackathonsList,
  HackathonsCreate,
  HackathonsEdit,
  HackathonsShow,
} from "./pages/hackathons";

function App() {
  return (
    <Refine
      dataProvider={dataProvider(supabaseClient)}
    >
      <Resource
        name="hackathons"
        list={HackathonsList}
        create={HackathonsCreate}
        edit={HackathonsEdit}
        show={HackathonsShow}
      />
    </Refine>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Alt Text

refine comes with builtin hooks for Ant design components. You can find detailed usage for the hooks and supabase in the documentation

Creating voting page

We'll use the dashboard option to place voting page. We'll need data from different resources. refine comes with powerful hooks that are based on react-query to get data from those resources.

For example to get the hackathons that are active now we can use the useList hook:

export const DashboardPage: React.FC = () => {
  const currentHackathons = useList<HackathonType>({
    resource: "hackathons",
    config: {
      filters: [
        {
          field: "start",
          operator: "lte",
          value: now,
        },
        {
          field: "end",
          operator: "gte",
          value: now,
        },
      ],
    },
  });
}
Enter fullscreen mode Exit fullscreen mode

We can get data from other resources in a similar fashion. You can find the codesandbox here and the repo here

Conclusion

This project itself is a product of a hackathon. It lacks lots of feature like authorization though it shows how refine makes it easy to quickly build a working app.

Sentry blog image

How to reduce TTFB

In the past few years in the web dev world, we’ve seen a significant push towards rendering our websites on the server. Doing so is better for SEO and performs better on low-powered devices, but one thing we had to sacrifice is TTFB.

In this article, we’ll see how we can identify what makes our TTFB high so we can fix it.

Read more

Top comments (0)

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay