Skip to content

huaiyukhaw/lastqr

Repository files navigation

LastQR

Create QR menus for your restaurant.

Try it! lastqr.huaiyukhaw.com

LastQR is a web-based application that allows restaurant customers to access menus via QR codes. The app was developed using modern web technologies, including React, Next.js, TailwindCSS, and Supabase.


Author

Huaiyu Khaw

Showcase

This project was designed to demonstrate:

  • Use of React with Typescript and TailwindCSS to build a modern and responsive user interface.
  • Utilization of a variety of libraies, such as @shortcm/qr-image for QR code generation and React Hot Toast for notifications.
  • Implementation of asynchronous programming techniques to fetch and manipulate data from a backend-as-a-service platform.

LastQR is a web-based application that allows restaurant customers to access menus via QR codes. The app was developed using modern web technologies, including React, Next.js, TailwindCSS, and Supabase.

The front-end of the app was built using React, which provides a component-based architecture for building user interfaces. I used Next.js as the framework to support server-side rendering, which improves the app's performance and search engine optimization. To design the app's user interface, I used TailwindCSS, a utility-first CSS framework that provides pre-built styles and classes for rapid development.

The app's functionality was implemented using React's state management and lifecycle methods, which provides interactivity and logic to the user interface. Specifically, the app uses React hooks to handle QR code scanning, API requests, and menu item selection. To ensure that the app is fast and responsive, I used asynchronous programming techniques, such as Promises and async/await, to handle API requests and prevent blocking the user interface. To fetch menu data from the back-end, the app uses Supabase, a backend-as-a-service platform that provides a PostgreSQL database and API.

During the development process, I used several development tools and libraries to improve my productivity and code quality. For example, I used Visual Studio Code as my code editor, and Git for version control. Additionally, I used a variety of libraries, including @shortcm/qr-image for QR code generation, and React Hot Toast for notifications.

Usage example

The usage of the QR Menu App is straightforward: diners simply scan the QR code using their smartphone's camera, and the app will take them to the restaurant's digital menu. From there, they can browse through the items, without the need for physical menus. This makes the dining experience more convenient and efficient, especially during busy hours.

Screenshots

image

image

image


Built With


Contributing

  1. Fork it (https://github.com/huaiyukhaw/lastqr/fork)
  2. Create your feature branch (git checkout -b feature/fooBar)
  3. Commit your changes (git commit -am 'Add some fooBar')
  4. Push to the branch (git push origin feature/fooBar)
  5. Create a new Pull Request

Environment variables .env.local

NEXT_PUBLIC_SUPABASE_URL= NEXT_PUBLIC_SUPABASE_ANON_KEY=


Development setup

npm install
npm run dev

Supabase setup

Run these queries at SQL editor of Supabase.

  • Create function generate_uid
CREATE OR REPLACE FUNCTION generate_uid(size INT) RETURNS TEXT AS $$
DECLARE
  characters TEXT := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  bytes BYTEA := gen_random_bytes(size);
  l INT := length(characters);
  i INT := 0;
  output TEXT := '';
BEGIN
  WHILE i < size LOOP
    output := output || substr(characters, get_byte(bytes, i) % l + 1, 1);
    i := i + 1;
  END LOOP;
  RETURN output;
END;
$$ LANGUAGE plpgsql VOLATILE;
  • Create Shops
-- Create a table for Public Shops
create table shops (
  id bigint generated by default as identity primary key,
  user_id uuid references auth.users not null,
  updated_at timestamp with time zone,
  username text unique DEFAULT generate_uid(6),
  cover_image text,
  logo text,
  establishment_name text,
  phone_number text,
  address text,
  currency text,
  language text,
  menus json[],
  
  unique(username),
  constraint username_length check (char_length(username) >= 3)
);

alter table shops
  enable row level security;

create policy "Public shops are viewable by everyone." on shops
  for select using (true);

create policy "Users can insert their own page." on shops
  for insert with check (auth.uid() = user_id);

create policy "Users can update own page." on shops
  for update using (auth.uid() = user_id);

-- Set up Realtime!
begin;
  drop publication if exists supabase_realtime;
  create publication supabase_realtime;
commit;
alter publication supabase_realtime
  add table shops;
  • Create Menus
-- Create a table for Public Menus
create table menus (
  id bigint generated by default as identity primary key,
  user_id uuid references auth.users not null,
  updated_at timestamp with time zone,
  slug text unique DEFAULT generate_uid(6),
  name text not null,
  collections json[],
  items json[],
  
  unique(slug),
  constraint slug_length check (char_length(slug) >= 3)
);

alter table menus
  enable row level security;

create policy "Public menus are viewable by everyone." on menus
  for select using (true);

create policy "Users can insert their own page." on menus
  for insert with check (auth.uid() = user_id);

create policy "Users can update own page." on menus
  for update using (auth.uid() = user_id);

-- Set up Realtime!
begin;
  drop publication if exists supabase_realtime;
  create publication supabase_realtime;
commit;
alter publication supabase_realtime
  add table menus;
  • Automatically update timestamp (for Shops table)
create extension if not exists moddatetime schema extensions;

-- assuming the table name is "shops", and a timestamp column "updated_at"
-- this trigger will set the "updated_at" column to the current timestamp for every update
create trigger
  handle_updated_at before update
on shops
for each row execute
  procedure moddatetime(updated_at);
  • Automatically update timestamp (for Menus table)
create extension if not exists moddatetime schema extensions;

-- assuming the table name is "menus", and a timestamp column "updated_at"
-- this trigger will set the "updated_at" column to the current timestamp for every update
create trigger
  handle_updated_at before update
on menus
for each row execute
  procedure moddatetime(updated_at);

Database Triggers

image

Database Functions

image

Database Schema

image

About

Create QR menus for your restaurant.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages