init commit,

This commit is contained in:
louiscklaw
2025-05-28 09:55:51 +08:00
commit efe70ceb69
8042 changed files with 951668 additions and 0 deletions

47
02_design/index.md Normal file
View File

@@ -0,0 +1,47 @@
# design
## POC:
### poc_supabase_budibase
- supabase
- budibase (admin frontend)
### poc_supabase_refine
- supabase
- refine
### poc_supabase_seeding
- [Seeding your database](https://supabase.com/docs/guides/cli/seeding-your-database)
### poc_connectivity
- supabase(real time db)
- ionic realtime chat
### poc_connectivity
- supabase
- ionic (perform CRUD)
### poc_supabase integration (Official Starters)
- https://github.com/lyqht/awesome-supabase
- Next.js, Slack Clone
- React
### poc_supabase_migration_example
- https://supabase.com/docs/guides/getting-started/tutorials/with-refine
- [design](#design)
- [POC](#poc)
- [poc_connectivity](#poc_connectivity)
- [poc_supabase_seeding](#poc_supabase_seeding)
- [poc_connectivity](#poc_connectivity-1)
- [poc_connectivity](#poc_connectivity-2)
- [poc_connectivity](#poc_connectivity-3)
- [poc_supabase integration (Official Starters):](#poc_supabase-integration-official-starters)
- [poc_supabase_migration_example](#poc_supabase_migration_example)

7
02_design/reset_permissions.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -ex
sudo chown 1000:1000 -R .
echo "done"

View File

@@ -0,0 +1,31 @@
const fs = require('fs');
const schemaSql = fs.readFileSync('schema.sql', 'utf8');
var schemaSqlTrimmed = schemaSql.replace(/^\n$/g, '');
schemaSqlTrimmed = schemaSqlTrimmed.replace(/\(\n/g, '(');
schemaSqlTrimmed = schemaSqlTrimmed.replace(/\n /g, ' ');
schemaSqlTrimmed = schemaSqlTrimmed.replace(/\n\)/g, ')');
schemaSqlTrimmed = schemaSqlTrimmed.replace(/,\n/g, '');
for (let i =0 ; i<10; i++){
schemaSqlTrimmed = schemaSqlTrimmed.replace(/\n\n/g, '\n');
}
// split schemaSqlTrimmed on 'by \n'
const schemaSqlSplit = schemaSqlTrimmed.split('\n');
const commentIndex = schemaSqlSplit.findIndex(line => line.match(/^COMMENT/));
const alterIndex = schemaSqlSplit.findIndex(line => line.match(/^ALTER/));
console.log({commentIndex, alterIndex});
const createSql = schemaSqlSplit.slice(0, commentIndex).join('\n');
fs.writeFileSync('create.sql', createSql);
const commentSql = schemaSqlSplit.slice(commentIndex, alterIndex).join('\n');
fs.writeFileSync('comment.sql', commentSql);
const alterSql = schemaSqlSplit.slice( alterIndex).join('\n');
fs.writeFileSync('alter.sql', '-- \n'+'-- alter.sql\n'+ '-- \n' + alterSql);
// console.log({schemaSqlTrimmed})

View File

@@ -0,0 +1,22 @@
// process fake_auth.user to auth.user
// 1. open `schema.sql`
const fs = require('fs');
const path = require('path');
var schema = fs.readFileSync(path.join(__dirname, 'schema.sql'), 'utf8');
var schema_before = schema
// 2. replace `CREATE TABLE "fake_auth.users" (*)` to ''
schema = schema.replace(/CREATE TABLE "fake_auth"\."users" \(.*?\);/gs, '-- fake_auth.users part syntax removed.');
if (schema.length == schema_before.length)
console.log("cannot replace !!!")
schema_before = schema
// 3. modify `REFERENCES "fake_auth.users"` to `REFERENCES "auth.users"`
schema = schema.replace(/REFERENCES "fake_auth"\."users"/g, 'REFERENCES auth.users');
if (schema.length == schema_before.length)
console.log("cannot replace !!!")
fs.writeFileSync(path.join(__dirname, 'schema.sql'), schema);
console.log("replace fake_auth.users to auth.users done . ")

1361
02_design/schema/output.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 166 KiB

View File

@@ -0,0 +1,372 @@
// HKSingleParty
Table fake_auth.users {
id uuid [pk]
username varchar
remarks text
}
// table above this line is from supabase, for graphing / generating sql
// filename: 002_message_status.sql
Table message_status {
id serial [pk]
title text [not null, default: ''] // read, unread
remarks text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'message read/unread status'
}
// REQ0002/vip-tag
// store user service rank,
// `not_vip`, not vip
// `vip`, vip user
Table user_rank {
id serial [pk]
title text [not null, default: '']
remarks text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store user vip status field'
}
// REQ0112/verified-tag
// store user verified status,
// `not_verified`, not verified
// `verified`, verified
Table user_verified {
id serial [pk]
title text [not null, default: '']
remarks text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store user verified field'
}
// REQ0092/user-other-tags
Table user_other_tags {
id serial [pk]
title text [not null, default: '']
remarks text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store user tags field'
}
// REQ0043/profile_detail
Table user_spoken_language {
id serial [pk]
title text [not null, default: '']
remarks text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store user spoken language field'
}
// REQ0094/user-career-filter
Table user_career {
id serial [pk]
title text [not null, default: '']
remarks text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store user career field'
}
// REQ0095/user-education-filter
Table user_education {
id serial [pk]
title text [not null, default: '']
remarks text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store user education field'
}
// REQ0051/notification
// to extend -> Database design for notification system
// https://tannguyenit95.medium.com/designing-a-notification-system-1da83ca971bc
Table notifications {
id serial [pk]
content text [not null, default: '']
remarks text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'handle admin send notification to user'
}
// REQ0047/order-page
// REQ0042/event-detail
// store party event cancelled, ongoing
Table party_event_status {
id serial [pk]
title text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store party event status'
}
// REQ0041/home_discover_event_tab
Table party_events {
id serial [pk]
title text [not null, default: '']
about_event text [not null, default: ''] // store about the event field
//
event_date TIMESTAMPTZ [not null, default: `now()`]
event_duration_min integer [not null, default: 90]
//
price integer [not null, default: 999]
currency text [not null, default: 'HKD']
last_payment_time TIMESTAMPTZ [not null, default: '2999-01-01']
//
address text [not null, default: '']
image_urls text[] [default: '{}']
//
status integer [not null, ref: > party_event_status.id, default: 0]
//
// replaced by party_event_orders table
// participants uuid [not null, ref: <> fake_auth.users.id]
join_boy integer [not null, default: 999]
join_girl integer [not null, default: 999]
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
remarks text [not null, default: '']
meta json [not null, default: `'{}'::json`]
//
note: 'store party events'
}
Table user_genders {
id serial [pk]
title text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`] // order time ?
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store user party event orders status'
}
// REQ0053/Profile-page
Table profiles {
// provided by supabase auth
id uuid [pk, ref: - fake_auth.users.id]
//
user_id serial [pk, unique]
website text [not null, default: '']
gender integer [not null, ref: - user_genders.id, default: 1]
// store user bookmarked event
bookmark_events integer [unique, ref: <> party_events.id]
// REQ0044/near_by_page
// TODO: fix coordinates later
// coordinates point [default: 'POINT(114.1759 22.3271)']
// REQ0099/profile-edit-form start
avatar_urls text[] [default: '{}']
about_user text [not null, default: '']
spoken_language integer [unique, ref: <> user_spoken_language.id]
career integer [unique, ref: <> user_career.id]
user_rank integer [unique, ref: <> user_rank.id] // store user vip rank
verified integer [unique, ref: - user_verified.id]
weight_kg integer [not null, default: 100]
height_cm integer [not null, default: 100]
education integer [unique, ref: - user_education.id]
other_tags integer [unique, ref: <> user_other_tags.id]
// REQ0099/profile-edit-form end
// store last onlnie information for My-nearby
last_seen TIMESTAMPTZ [not null, default: `now()`]
// get age
year_of_birth integer [default: 1970] // default to Jan-01 to get age
// REQ0051/notification
notification_read integer [unique, ref: <> notifications.id]
// REQ0051/notification
block_user_id text[] [not null, default: '{}']
// handle user delete account
// is_user_suspend -> user delete account
// is_admin_suspend -> admin delete user account
suspend_at TIMESTAMPTZ [default: '2999-01-01']
is_user_suspend integer [not null, default: 0] // 0 => not suspended
is_admin_suspend integer [not null, default: 0] // 0 => not suspended
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store user meta'
}
// REQ0050/chat-room-list (messages)
Table messages {
id serial [pk]
content text [not null, default: '']
media_url varchar(255)
sender_user_id integer [not null, ref: > profiles.user_id]
receiver_user_id integer [not null, ref: > profiles.user_id]
// NOTE: ?? not sure correct or not for these
// message_arrived integer [not null, unique, ref: <> profiles.user_id]
// message_read integer [not null, unique, ref: <> profiles.user_id]
// message_archived integer [not null, unique, ref: <> profiles.user_id]
// message_deleted integer [not null, unique, ref: <> profiles.user_id]
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store in-app chat'
}
Table visit_user_profile_read_status {
id serial [pk]
title text [not null, default: ''] // unread -> read
remarks text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store visit status read by host'
}
// REQ0050/chat-room-list
// visitor => some people visit host profile
// host => profile that visitor visit
// on host perspective, store who visit host profile
Table visit_user_profile {
id serial [pk]
//
visitor_user_id integer [not null, ref: > profiles.user_id]
visit_at TIMESTAMPTZ [not null, default: `now()`]
// question, why i think `<` is correct ?
host_user_id integer [not null, ref: > profiles.user_id]
host_user_read integer [not null, ref: > visit_user_profile_read_status.id, default: 1]
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
remarks text [not null, default: '']
//
note: 'history list, store user profile visited by others, used in near-by page'
}
// not-paid, user not paid for event
// paid, user paid for event
Table party_event_order_status {
id serial [pk]
title text [not null, default: ''] // pending, paid
remarks text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`] // order time ?
update_at TIMESTAMPTZ [not null, default: `now()`]
meta json [not null, default: `'{}'::json`]
//
note: 'store user party event orders status'
}
// REQ0047/order-page
Table party_event_orders {
id serial [pk]
user_id integer [not null, ref: - profiles.user_id]
party_event_id integer [not null, ref: - party_events.id]
//
status integer [not null, ref: - party_event_order_status.id]
payment_time TIMESTAMPTZ [not null, default: '2999-01-01']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`] // order time
update_at TIMESTAMPTZ [not null, default: `now()`]
remarks text [default: '']
meta json [not null, default: `'{}'::json`]
//
note: 'store user party event orders'
}
// REQ0057/contact-support
Table contact_us_message {
id serial [pk]
content text [not null, default: '']
attachments text[] [default: '{}']
read_status integer [not null, ref: - message_status.id, default: 1]
//
from_user_id integer [not null, ref: - profiles.user_id]
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
remarks text [not null, default: '']
meta json [not null, default: `'{}'::json`]
//
note: 'store user to admin messages'
}
// REQ0084/select-report-category
Table report_user_reason {
id serial [pk]
content text [not null, default: '']
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
remarks text [not null, default: '']
meta json [not null, default: `'{}'::json`]
//
note: 'store user to admin messages'
}
// REQ0046/report-form
Table report_user {
id serial [pk]
content text [not null, default: '']
attachments text[] [default: '{}']
reason integer [not null, ref: - report_user_reason.id]
//
report_user_id integer [not null, ref: - profiles.user_id] // store user id to report
from_user_id integer [not null, ref: - profiles.user_id] // store report sender
//
create_at TIMESTAMPTZ [not null, default: `CURRENT_TIMESTAMP`]
update_at TIMESTAMPTZ [not null, default: `now()`]
remarks text [not null, default: '']
meta json [not null, default: `'{}'::json`]
//
note: 'store report user messages'
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

21
02_design/schema/update.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -ex
# Install pre-requisites
# npm install -g @softwaretechnik/dbml-renderer
# TO RUN
#
# cd /home/logic/_wsl_workspace/HKSingleParty/02_design/schema
# nodemon --ext dbml -w . --exec "./update.sh"
#
npx -p @dbml/cli dbml2sql ./schema.dbml -o ./schema.sql
npx dbml-renderer -i schema.dbml -o output.svg
# process fake_auth.user to auth.user
node ./modify_fake_table.js
# move to target sql file
mv ./schema.sql ../../04_poc/009_poc_chatroom_implement/docker/supabase/migrations/00003_party_schema_dbml.sql

26
02_design/tables.md Normal file
View File

@@ -0,0 +1,26 @@
# tables.md
### table check list
| `table` | `insert sample data` |
| -------------------------- | :------------------: |
| `message_status` | ✅ |
| `user_rank` | ✅ |
| `user_verified` | ✅ |
| `user_other_tags` | ✅ |
| `user_spoken_language` | ✅ |
| `user_career` | ✅ |
| `user_education` | ✅ |
| `notifications` | ✅ |
| `party_event_status` | ✅ |
| `party_events` | ✅ |
| `user_genders` | ✅ |
| `visit_user_status` | ✅ |
| `contact_us_message` | ✅ |
| `report_user_reason` | ✅ |
| `report_user` | ✅ |
| `messages` | ✅ |
| `profiles` | ✅ |
| `visit_user_profile` | ✅ |
| `party_event_order_status` | ✅ |
| `party_event_orders` | |

17
02_design/time_track.md Normal file
View File

@@ -0,0 +1,17 @@
```mermaid
gantt
title Project time track
dateFormat YYYY-MM-DD
section Section
poc :poc, 2024-08-30, 3d
code android :android, after poc, 30d
code admin panel :admin, after android, 30d
code ios :after admin, 30d
section Another
Task in Another :2024-08-30, 12d
another task :24d
```