diff --git a/.env.example b/.env.example
index 1306a42..fa9a947 100644
--- a/.env.example
+++ b/.env.example
@@ -1,8 +1,9 @@
-DATABASE_URL="postgres://username:password@host/database?ssl=true"
S3_ENDPOINT=""
S3_ACCESS_KEY=""
S3_SECRET_KEY=""
-S3_BUCKET_NAME="bangmod-hackathon-2024"
+S3_BUCKET_NAME=""
-GOOGLE_EMAIL=
-GOOGLE_EMAIL_PASSWORD=
\ No newline at end of file
+SUPABASE_ANON_KEY=""
+SUPABASE_URL=""
+
+BREVO_KEY=""
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 6635cf5..8c3a9af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,5 @@ node_modules
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
+/tests/
+supabase
diff --git a/.prettierrc b/.prettierrc
index ea3657f..9ba7289 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,5 +1,6 @@
{
"useTabs": true,
+ "endOfLine": "crlf",
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
diff --git a/package.json b/package.json
index dc3c428..4e43b32 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
"@supabase/supabase-js": "^2.38.4",
"@sveltejs/adapter-auto": "^2.1.0",
"@sveltejs/adapter-cloudflare": "^2.3.3",
+ "@sveltejs/adapter-cloudflare-workers": "^1.2.0",
"@sveltejs/kit": "^1.25.2",
"@types/lodash.set": "^4.3.8",
"@typescript-eslint/eslint-plugin": "^6.7.5",
@@ -42,8 +43,10 @@
"prettier": "^3.0.3",
"prettier-plugin-svelte": "^3.0.3",
"prettier-plugin-tailwindcss": "^0.5.6",
+ "supabase": "^1.115.4",
"svelte": "^4.2.1",
"svelte-check": "^3.5.2",
+ "svelte-inview": "^4.0.1",
"sveltekit-superforms": "^1.8.0",
"tailwind-merge": "^1.14.0",
"tailwindcss": "^3.3.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bf9f77b..dfb71c4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -28,6 +28,9 @@ devDependencies:
'@sveltejs/adapter-cloudflare':
specifier: ^2.3.3
version: 2.3.3(@sveltejs/kit@1.25.2)
+ '@sveltejs/adapter-cloudflare-workers':
+ specifier: ^1.2.0
+ version: 1.2.0(@sveltejs/kit@1.25.2)
'@sveltejs/kit':
specifier: ^1.25.2
version: 1.25.2(svelte@4.2.1)(vite@4.4.11)
@@ -79,12 +82,18 @@ devDependencies:
prettier-plugin-tailwindcss:
specifier: ^0.5.6
version: 0.5.6(prettier-plugin-svelte@3.0.3)(prettier@3.0.3)
+ supabase:
+ specifier: ^1.115.4
+ version: 1.115.4
svelte:
specifier: ^4.2.1
version: 4.2.1
svelte-check:
specifier: ^3.5.2
version: 3.5.2(postcss@8.4.31)(svelte@4.2.1)
+ svelte-inview:
+ specifier: ^4.0.1
+ version: 4.0.1(svelte@4.2.1)
sveltekit-superforms:
specifier: ^1.8.0
version: 1.8.0(@sveltejs/kit@1.25.2)(svelte@4.2.1)(zod@3.22.4)
@@ -995,6 +1004,10 @@ packages:
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
dev: true
+ /@iarna/toml@2.2.5:
+ resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==}
+ dev: true
+
/@jest/schemas@29.6.3:
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -1562,6 +1575,17 @@ packages:
import-meta-resolve: 3.0.0
dev: true
+ /@sveltejs/adapter-cloudflare-workers@1.2.0(@sveltejs/kit@1.25.2):
+ resolution: {integrity: sha512-H1QIb5cJquleWw93awBX8FYZLFDA+ZXvGtZspACwDNDty/JCSBFPFRC1FOt5mFRy6Q0lbxwGMpo/LgLXcDtW/w==}
+ peerDependencies:
+ '@sveltejs/kit': ^1.0.0
+ dependencies:
+ '@cloudflare/workers-types': 4.20231010.0
+ '@iarna/toml': 2.2.5
+ '@sveltejs/kit': 1.25.2(svelte@4.2.1)(vite@4.4.11)
+ esbuild: 0.18.20
+ dev: true
+
/@sveltejs/adapter-cloudflare@2.3.3(@sveltejs/kit@1.25.2):
resolution: {integrity: sha512-bbcm6kq4dEluFtFJZed3KSRG4f5GUElYkVfOmnPruTqZ29nTElPJTomAu5QCp7GLkwA26O3h1Dk7+d9yLTQEXg==}
peerDependencies:
@@ -1885,6 +1909,15 @@ packages:
hasBin: true
dev: true
+ /agent-base@7.1.0:
+ resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==}
+ engines: {node: '>= 14'}
+ dependencies:
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
dependencies:
@@ -2043,6 +2076,16 @@ packages:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
dev: false
+ /bin-links@4.0.3:
+ resolution: {integrity: sha512-obsRaULtJurnfox/MDwgq6Yo9kzbv1CPTk/1/s7Z/61Lezc8IKkFCOXNeVLXz0456WRzBQmSsDWlai2tIhBsfA==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ dependencies:
+ cmd-shim: 6.0.2
+ npm-normalize-package-bin: 3.0.1
+ read-cmd-shim: 4.0.0
+ write-file-atomic: 5.0.1
+ dev: true
+
/binary-extensions@2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
@@ -2165,6 +2208,16 @@ packages:
fsevents: 2.3.3
dev: true
+ /chownr@2.0.0:
+ resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /cmd-shim@6.0.2:
+ resolution: {integrity: sha512-+FFYbB0YLaAkhkcrjkyNLYDiOsFSfRjwjY19LXk/psmMx1z00xlCv7hhQoTGXXIKi+YXHL/iiFo8NqMVQX9nOw==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ dev: true
+
/code-red@1.0.4:
resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==}
dependencies:
@@ -2230,6 +2283,11 @@ packages:
type: 1.2.0
dev: true
+ /data-uri-to-buffer@4.0.1:
+ resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
+ engines: {node: '>= 12'}
+ dev: true
+
/debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
@@ -2791,6 +2849,14 @@ packages:
reusify: 1.0.4
dev: true
+ /fetch-blob@3.2.0:
+ resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
+ engines: {node: ^12.20 || >= 14.13}
+ dependencies:
+ node-domexception: 1.0.0
+ web-streams-polyfill: 3.2.1
+ dev: true
+
/file-entry-cache@6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
@@ -2832,10 +2898,24 @@ packages:
is-callable: 1.2.7
dev: true
+ /formdata-polyfill@4.0.10:
+ resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
+ engines: {node: '>=12.20.0'}
+ dependencies:
+ fetch-blob: 3.2.0
+ dev: true
+
/fraction.js@4.3.7:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
dev: true
+ /fs-minipass@2.1.0:
+ resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ minipass: 3.3.6
+ dev: true
+
/fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: true
@@ -3029,6 +3109,16 @@ packages:
function-bind: 1.1.2
dev: true
+ /https-proxy-agent@7.0.2:
+ resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==}
+ engines: {node: '>= 14'}
+ dependencies:
+ agent-base: 7.1.0
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
dev: false
@@ -3370,6 +3460,26 @@ packages:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
dev: true
+ /minipass@3.3.6:
+ resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
+ engines: {node: '>=8'}
+ dependencies:
+ yallist: 4.0.0
+ dev: true
+
+ /minipass@5.0.0:
+ resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /minizlib@2.1.2:
+ resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ minipass: 3.3.6
+ yallist: 4.0.0
+ dev: true
+
/mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true
@@ -3377,6 +3487,12 @@ packages:
minimist: 1.2.8
dev: true
+ /mkdirp@1.0.4:
+ resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dev: true
+
/mlly@1.4.2:
resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==}
dependencies:
@@ -3426,6 +3542,20 @@ packages:
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
dev: true
+ /node-domexception@1.0.0:
+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+ engines: {node: '>=10.5.0'}
+ dev: true
+
+ /node-fetch@3.3.2:
+ resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ data-uri-to-buffer: 4.0.1
+ fetch-blob: 3.2.0
+ formdata-polyfill: 4.0.10
+ dev: true
+
/node-gyp-build@4.6.1:
resolution: {integrity: sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==}
hasBin: true
@@ -3445,6 +3575,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
+ /npm-normalize-package-bin@3.0.1:
+ resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ dev: true
+
/object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
@@ -3844,6 +3979,11 @@ packages:
pify: 2.3.0
dev: true
+ /read-cmd-shim@4.0.0:
+ resolution: {integrity: sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ dev: true
+
/readable-stream@3.6.2:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
@@ -4023,6 +4163,11 @@ packages:
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
dev: true
+ /signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+ dev: true
+
/sirv@2.0.3:
resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==}
engines: {node: '>= 10'}
@@ -4146,6 +4291,20 @@ packages:
ts-interface-checker: 0.1.13
dev: true
+ /supabase@1.115.4:
+ resolution: {integrity: sha512-VXfz9riWHKEmbzv8ITJuqVCVl/92DLhKvUMiU9tVwCBylMWMqg0hOoh89VSZETektZOtxXk24jCQ9zrBqodzKQ==}
+ engines: {npm: '>=8'}
+ hasBin: true
+ requiresBuild: true
+ dependencies:
+ bin-links: 4.0.3
+ https-proxy-agent: 7.0.2
+ node-fetch: 3.3.2
+ tar: 6.2.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
/supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@@ -4211,6 +4370,14 @@ packages:
svelte: 4.2.1
dev: true
+ /svelte-inview@4.0.1(svelte@4.2.1):
+ resolution: {integrity: sha512-8NuT/DKFiZAccDw1Z16cIsdZ7K6/BGxrUfDaFaWTCEdn3YqMj1TUAkfmQ08FQ1+INl1G+TQS+ImXIBiiISgXog==}
+ peerDependencies:
+ svelte: ^3.0.0 || ^4.0.0
+ dependencies:
+ svelte: 4.2.1
+ dev: true
+
/svelte-preprocess@5.0.4(postcss@8.4.31)(svelte@4.2.1)(typescript@5.2.2):
resolution: {integrity: sha512-ABia2QegosxOGsVlsSBJvoWeXy1wUKSfF7SWJdTjLAbx/Y3SrVevvvbFNQqrSJw89+lNSsM58SipmZJ5SRi5iw==}
engines: {node: '>= 14.10.0'}
@@ -4330,6 +4497,18 @@ packages:
engines: {node: '>=6'}
dev: true
+ /tar@6.2.0:
+ resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ chownr: 2.0.0
+ fs-minipass: 2.1.0
+ minipass: 5.0.0
+ minizlib: 2.1.2
+ mkdirp: 1.0.4
+ yallist: 4.0.0
+ dev: true
+
/text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
dev: true
@@ -4683,6 +4862,11 @@ packages:
- terser
dev: true
+ /web-streams-polyfill@3.2.1:
+ resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==}
+ engines: {node: '>= 8'}
+ dev: true
+
/webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
dev: true
@@ -4758,6 +4942,14 @@ packages:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: true
+ /write-file-atomic@5.0.1:
+ resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ dependencies:
+ imurmurhash: 0.1.4
+ signal-exit: 4.1.0
+ dev: true
+
/yaeti@0.0.6:
resolution: {integrity: sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==}
engines: {node: '>=0.10.32'}
diff --git a/src/app.html b/src/app.html
index 132ac21..228b702 100644
--- a/src/app.html
+++ b/src/app.html
@@ -1,18 +1,46 @@
+
-
+
+
+
+
+
+
+
+
+
+
+
+
%sveltekit.head%
-
+
%sveltekit.body%
+
+
+
diff --git a/src/lib/components/forms/CheckBox.svelte b/src/lib/components/forms/CheckBox.svelte
index c20feb9..e41039f 100644
--- a/src/lib/components/forms/CheckBox.svelte
+++ b/src/lib/components/forms/CheckBox.svelte
@@ -9,7 +9,7 @@
export let required: boolean = false;
const borderClasses = {
- base: 'border-iron-300 focus:border-iron-800 focus:border-2',
+ base: 'border-[#47537C] focus:border-iron-800 focus:border-2',
red: 'border-scarlet-800 focus:border-scarlet-900 focus:border-2'
};
diff --git a/src/lib/components/forms/ComboBox.svelte b/src/lib/components/forms/ComboBox.svelte
index bf7dca3..64d5e89 100644
--- a/src/lib/components/forms/ComboBox.svelte
+++ b/src/lib/components/forms/ComboBox.svelte
@@ -64,8 +64,8 @@
};
const colorClasses = {
- base: 'bg-soapstone text-asphalt',
- red: 'bg-soapstone text-scarlet-800 placeholder-scarlet-800'
+ base: 'bg-[#fff9ed] text-asphalt',
+ red: 'bg-[#fff9ed] text-scarlet-800 placeholder-scarlet-800'
};
const defaultClasses = {
@@ -105,7 +105,7 @@
on:paste
on:input
autocomplete="off"
- class="peer w-full font-light outline-none"
+ class="peer w-full font-light outline-none bg-[#fff9ed]"
bind:value
/>
diff --git a/src/lib/components/forms/Input.svelte b/src/lib/components/forms/Input.svelte
index 215f917..d85a420 100644
--- a/src/lib/components/forms/Input.svelte
+++ b/src/lib/components/forms/Input.svelte
@@ -7,13 +7,13 @@
export let required: boolean = false;
const borderClasses = {
- base: 'border-iron-300 focus:border-iron-800 focus:border-2 invalid:border-scarlet-800 invalid:focus:border-scarlet-900',
+ base: 'border-iron-300 focus:border-iron-800 focus:border-2 invalid:[&:not(:placeholder-shown):not(:focus)]:border-scarlet-800 invalid:not(:placeholder-shown):focus:border-scarlet-900',
red: 'border-scarlet-800 focus:border-scarlet-900 focus:border-2'
};
const colorClasses = {
- base: 'bg-soapstone text-asphalt invalid:text-scarlet-800 invalid:placeholder-scarlet-800',
- red: 'bg-soapstone text-scarlet-800 placeholder-scarlet-800'
+ base: 'bg-[#fff9ed] text-asphalt invalid:[&:not(:placeholder-shown):not(:focus)]:text-scarlet-800 invalid:[&:not(:placeholder-shown):not(:focus)]:placeholder-scarlet-800',
+ red: 'bg-[#fff9ed] text-scarlet-800 placeholder-scarlet-800'
};
const defaultClass =
@@ -46,11 +46,12 @@
on:input
class={inputClass}
bind:value
+ required={required}
/>
diff --git a/src/lib/components/homes/About.svelte b/src/lib/components/homes/About.svelte
new file mode 100644
index 0000000..d6213a9
--- /dev/null
+++ b/src/lib/components/homes/About.svelte
@@ -0,0 +1,32 @@
+
+
+
+
+
+ BangMod Hackathon 2024
+ คืออะไร ?
+
+
+
+
+
+
+ โครงการแข่งขันการเขียนโปรแกรมคอมพิวเตอร์ BangMod Hackathon 2024
+ เป็นโครงการที่เปิดโอกาสให้นักเรียนระดับชั้นมัธยมศึกษาตอนต้น และตอนปลาย
+ รวมถึงนักศึกษาอาชีวศึกษาในระดับ ปวช. หรือเทียบเท่า ได้เข้ามาแข่งขันการเขียน โปรแกรม
+ โดยใช้ภาษาซี ซึ่งการแข่งขันนั้นจะเป็นการแข่งขันในรูปแบบทีม
+ ทำให้ผู้เข้าแข่งขันนั้นได้รับทั้งประสบการณ์ใหม่ ๆ ในการเขียนโปรแกรม
+ และฝึกการทำงานร่วมกันเป็นทีมอีกด้วย
+
+
+
+
diff --git a/src/lib/components/homes/Award.svelte b/src/lib/components/homes/Award.svelte
new file mode 100644
index 0000000..be43163
--- /dev/null
+++ b/src/lib/components/homes/Award.svelte
@@ -0,0 +1,43 @@
+
+
+
+
+
รางวัล
+
+
+
+ {#each awards as award}
+
+
+
{award.name}
+
+ {award.reward}
+
+
+ {/each}
+
+
+
+
diff --git a/src/lib/components/homes/Contact.svelte b/src/lib/components/homes/Contact.svelte
new file mode 100644
index 0000000..cc46cc4
--- /dev/null
+++ b/src/lib/components/homes/Contact.svelte
@@ -0,0 +1,72 @@
+
+
+
+
+
+ ติดต่อเรา
+
+
+
+
+
+
+
+
+
+
BANGMOD HACKATHON 2024
+
+
+
+ CHAT NOW
+
+
+
+
+
+
+
+ {#each staffs as { name, phone }}
+
+
+ {phone}
+
+
+ {name}
+
+
+ {/each}
+
+
+
+
+
+
+
+
+ ภาควิชาวิศวกรรมคอมพิวเตอร์ คณะวิศวกรรมศาสตร์
มหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรี
+
ชั้น 10 อาคารวิศววัฒนะ 126 ถนนประชาอุทิศ แขวงบางมด เขตทุ่งครุ กรุงเทพฯ 10140
+
+
diff --git a/src/lib/components/homes/Hero.svelte b/src/lib/components/homes/Hero.svelte
new file mode 100644
index 0000000..e429233
--- /dev/null
+++ b/src/lib/components/homes/Hero.svelte
@@ -0,0 +1,21 @@
+
+
+
+
Bangmod Hackathon 2024
+
+
+
+
+
+
+
diff --git a/src/lib/components/homes/Qualification.svelte b/src/lib/components/homes/Qualification.svelte
new file mode 100644
index 0000000..7a113db
--- /dev/null
+++ b/src/lib/components/homes/Qualification.svelte
@@ -0,0 +1,92 @@
+
+
+
+
+
+ คุณสมบัติผู้สมัคร
+
+
+
+
+
+
+
+
+ {#each qualifications as qualify}
+
+ {/each}
+
+
+
+
+
+
+ เอกสารที่ใช้ในการรับสมัคร
+
+
+
+
+
+
+
+
+
อาจารย์ที่ปรึกษา
+ {#each teacher_files as teacher_file}
+
+ {/each}
+
+
+
+
+
+
+
+
+
+
+
นักเรียน
+ {#each student_files as student_file}
+
+ {/each}
+
+
+
+
+
diff --git a/src/lib/components/homes/Scope.svelte b/src/lib/components/homes/Scope.svelte
new file mode 100644
index 0000000..bae1dab
--- /dev/null
+++ b/src/lib/components/homes/Scope.svelte
@@ -0,0 +1,150 @@
+
+
+
+
+
+ ขอบเขตเนื้อหาที่ใช้ในการแข่งขัน
+
+
+
+
+ {#each scopes as { topic, contents }, idx}
+
+
+ {#if openTabs.includes(idx)}
+
+
+ {#each contents as { name, lists }}
+ - {name}
+ {#if lists.length > 0}
+
+ {#each lists as item (item)}
+ - {item}
+ {/each}
+
+ {/if}
+ {/each}
+
+
+ {/if}
+
+ {/each}
+
+
+
diff --git a/src/lib/components/homes/Timeline.svelte b/src/lib/components/homes/Timeline.svelte
new file mode 100644
index 0000000..1f893d8
--- /dev/null
+++ b/src/lib/components/homes/Timeline.svelte
@@ -0,0 +1,154 @@
+
+
+
+
+
+
+
+
+ {#each timelines as timeline, idx}
+
+
+
+
+
+ {timeline.name}
+
+
+ {timeline.date}
+
+
+
+
+ {/each}
+
+
+
+ {#each timelines as timeline, idx}
+
+
+
+
+
+ {timeline.name}
+
+
+ {timeline.date}
+
+
+
+ ⇣
+
+
+
+ {/each}
+
+
+
+
+
diff --git a/src/lib/components/homes/index.ts b/src/lib/components/homes/index.ts
new file mode 100644
index 0000000..07af669
--- /dev/null
+++ b/src/lib/components/homes/index.ts
@@ -0,0 +1,7 @@
+export { default as About } from './About.svelte';
+export { default as Award } from './Award.svelte';
+export { default as Contact } from './Contact.svelte';
+export { default as Hero } from './Hero.svelte';
+export { default as Qualification } from './Qualification.svelte';
+export { default as Scope } from './Scope.svelte';
+export { default as Timeline } from './Timeline.svelte';
diff --git a/src/lib/components/icons/ArrowDown.svelte b/src/lib/components/icons/ArrowDown.svelte
new file mode 100644
index 0000000..a54adc8
--- /dev/null
+++ b/src/lib/components/icons/ArrowDown.svelte
@@ -0,0 +1,18 @@
+
+
+
diff --git a/src/lib/components/icons/ArrowRight.svelte b/src/lib/components/icons/ArrowRight.svelte
new file mode 100644
index 0000000..4b04c5d
--- /dev/null
+++ b/src/lib/components/icons/ArrowRight.svelte
@@ -0,0 +1,17 @@
+
+
+
diff --git a/src/lib/components/icons/Facebook.svelte b/src/lib/components/icons/Facebook.svelte
new file mode 100644
index 0000000..b93aabb
--- /dev/null
+++ b/src/lib/components/icons/Facebook.svelte
@@ -0,0 +1,16 @@
+
+
+
diff --git a/src/lib/components/icons/Hamburger.svelte b/src/lib/components/icons/Hamburger.svelte
new file mode 100644
index 0000000..8d24bdb
--- /dev/null
+++ b/src/lib/components/icons/Hamburger.svelte
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/src/lib/components/icons/Telephone.svelte b/src/lib/components/icons/Telephone.svelte
new file mode 100644
index 0000000..a8141de
--- /dev/null
+++ b/src/lib/components/icons/Telephone.svelte
@@ -0,0 +1,20 @@
+
+
+
diff --git a/src/lib/components/icons/index.ts b/src/lib/components/icons/index.ts
index f8ee54a..0b9f44a 100644
--- a/src/lib/components/icons/index.ts
+++ b/src/lib/components/icons/index.ts
@@ -2,4 +2,9 @@ export { default as Calendar } from './Calendar.svelte';
export { default as Check } from './Check.svelte';
export { default as ChevronDown } from './ChevronDown.svelte';
export { default as Upload } from './Upload.svelte';
-export { default as Spinner } from './Spinner.svelte';
\ No newline at end of file
+export { default as ArrowDown } from './ArrowDown.svelte';
+export { default as ArrowRight } from './ArrowRight.svelte';
+export { default as Spinner } from './Spinner.svelte';
+export { default as Hamburger } from './Hamburger.svelte';
+export { default as Facebook } from './Facebook.svelte';
+export { default as Telephone } from './Telephone.svelte';
diff --git a/src/lib/components/utils/Circular.svelte b/src/lib/components/utils/Circular.svelte
new file mode 100644
index 0000000..07215bb
--- /dev/null
+++ b/src/lib/components/utils/Circular.svelte
@@ -0,0 +1,29 @@
+
+
+
diff --git a/src/lib/components/utils/index.ts b/src/lib/components/utils/index.ts
new file mode 100644
index 0000000..298ae2f
--- /dev/null
+++ b/src/lib/components/utils/index.ts
@@ -0,0 +1 @@
+export { default as CircularText } from './Circular.svelte';
diff --git a/src/lib/components/vectors/Elements/Cookies01.svelte b/src/lib/components/vectors/Elements/Cookies01.svelte
new file mode 100644
index 0000000..b62fb1f
--- /dev/null
+++ b/src/lib/components/vectors/Elements/Cookies01.svelte
@@ -0,0 +1,21 @@
+
+
+
diff --git a/src/lib/components/vectors/Elements/Custard.svelte b/src/lib/components/vectors/Elements/Custard.svelte
new file mode 100644
index 0000000..0e0a960
--- /dev/null
+++ b/src/lib/components/vectors/Elements/Custard.svelte
@@ -0,0 +1,22 @@
+
+
+
diff --git a/src/lib/components/vectors/Elements/Eclairs01.svelte b/src/lib/components/vectors/Elements/Eclairs01.svelte
new file mode 100644
index 0000000..51403ec
--- /dev/null
+++ b/src/lib/components/vectors/Elements/Eclairs01.svelte
@@ -0,0 +1,20 @@
+
+
+
diff --git a/src/lib/components/vectors/Elements/IceCream02.svelte b/src/lib/components/vectors/Elements/IceCream02.svelte
new file mode 100644
index 0000000..97ec2a2
--- /dev/null
+++ b/src/lib/components/vectors/Elements/IceCream02.svelte
@@ -0,0 +1,17 @@
+
+
+
diff --git a/src/lib/components/vectors/Elements/Jelly.svelte b/src/lib/components/vectors/Elements/Jelly.svelte
new file mode 100644
index 0000000..875e838
--- /dev/null
+++ b/src/lib/components/vectors/Elements/Jelly.svelte
@@ -0,0 +1,47 @@
+
+
+
diff --git a/src/lib/components/vectors/Elements/Macarons01.svelte b/src/lib/components/vectors/Elements/Macarons01.svelte
new file mode 100644
index 0000000..0815147
--- /dev/null
+++ b/src/lib/components/vectors/Elements/Macarons01.svelte
@@ -0,0 +1,17 @@
+
+
+
diff --git a/src/lib/components/vectors/Elements/Macarons02.svelte b/src/lib/components/vectors/Elements/Macarons02.svelte
new file mode 100644
index 0000000..b6bbd4e
--- /dev/null
+++ b/src/lib/components/vectors/Elements/Macarons02.svelte
@@ -0,0 +1,37 @@
+
+
+
diff --git a/src/lib/components/vectors/Elements/Pretzel.svelte b/src/lib/components/vectors/Elements/Pretzel.svelte
new file mode 100644
index 0000000..364a8b8
--- /dev/null
+++ b/src/lib/components/vectors/Elements/Pretzel.svelte
@@ -0,0 +1,18 @@
+
+
+
diff --git a/src/lib/components/vectors/Elements/SundayStudent3.svelte b/src/lib/components/vectors/Elements/SundayStudent3.svelte
new file mode 100644
index 0000000..a8d741e
--- /dev/null
+++ b/src/lib/components/vectors/Elements/SundayStudent3.svelte
@@ -0,0 +1,26 @@
+
+
+
diff --git a/src/lib/components/vectors/Elements/SundayTeacher.svelte b/src/lib/components/vectors/Elements/SundayTeacher.svelte
new file mode 100644
index 0000000..2867882
--- /dev/null
+++ b/src/lib/components/vectors/Elements/SundayTeacher.svelte
@@ -0,0 +1,28 @@
+
+
+
diff --git a/src/lib/components/vectors/Elements/SundayTeam.svelte b/src/lib/components/vectors/Elements/SundayTeam.svelte
new file mode 100644
index 0000000..bd89abb
--- /dev/null
+++ b/src/lib/components/vectors/Elements/SundayTeam.svelte
@@ -0,0 +1,72 @@
+
+
+
+
+
diff --git a/src/lib/components/vectors/Elements/index.ts b/src/lib/components/vectors/Elements/index.ts
new file mode 100644
index 0000000..d8f037a
--- /dev/null
+++ b/src/lib/components/vectors/Elements/index.ts
@@ -0,0 +1,11 @@
+export { default as SundayTeacher } from './SundayTeacher.svelte';
+export { default as SundayStudent3 } from './SundayStudent3.svelte';
+export { default as SundayTeam } from './SundayTeam.svelte';
+export { default as Macarons01 } from './Macarons01.svelte';
+export { default as Macarons02 } from './Macarons02.svelte';
+export { default as IceCream02 } from './IceCream02.svelte';
+export { default as Eclairs01 } from './Eclairs01.svelte';
+export { default as Custard } from './Custard.svelte';
+export { default as Jelly } from './Jelly.svelte';
+export { default as Cookies01 } from './Cookies01.svelte';
+export { default as Pretzel } from './Pretzel.svelte';
diff --git a/src/lib/components/vectors/Icon.svelte b/src/lib/components/vectors/Icon.svelte
new file mode 100644
index 0000000..3758b54
--- /dev/null
+++ b/src/lib/components/vectors/Icon.svelte
@@ -0,0 +1,80 @@
+
+
diff --git a/src/lib/components/vectors/Trophies/TrophySecond.svelte b/src/lib/components/vectors/Trophies/TrophySecond.svelte
new file mode 100644
index 0000000..f05621c
--- /dev/null
+++ b/src/lib/components/vectors/Trophies/TrophySecond.svelte
@@ -0,0 +1,139 @@
+
+
+
diff --git a/src/lib/components/vectors/Trophies/TrophyThird.svelte b/src/lib/components/vectors/Trophies/TrophyThird.svelte
new file mode 100644
index 0000000..5ec5ea0
--- /dev/null
+++ b/src/lib/components/vectors/Trophies/TrophyThird.svelte
@@ -0,0 +1,120 @@
+
+
+
diff --git a/src/lib/components/vectors/Trophies/TrophyWinner.svelte b/src/lib/components/vectors/Trophies/TrophyWinner.svelte
new file mode 100644
index 0000000..938d23b
--- /dev/null
+++ b/src/lib/components/vectors/Trophies/TrophyWinner.svelte
@@ -0,0 +1,160 @@
+
+
+
diff --git a/src/lib/components/vectors/index.ts b/src/lib/components/vectors/index.ts
new file mode 100644
index 0000000..7b951fd
--- /dev/null
+++ b/src/lib/components/vectors/index.ts
@@ -0,0 +1,5 @@
+export { default as TrophyWinner } from './Trophies/TrophyWinner.svelte';
+export { default as TrophySecond } from './Trophies/TrophySecond.svelte';
+export { default as TrophyThird } from './Trophies/TrophyThird.svelte';
+export { default as Icon } from './Icon.svelte';
+export * from './Elements';
diff --git a/src/lib/server/email.ts b/src/lib/server/email.ts
index fdcb5eb..0026f60 100644
--- a/src/lib/server/email.ts
+++ b/src/lib/server/email.ts
@@ -26,11 +26,7 @@ const sendEmail = async (htmlContent: string, to: { email: string; name: string
body: JSON.stringify(data)
});
- if (!response.ok) {
- throw new Error(await response.text());
- }
-
- return true;
+ return response.ok;
};
const prepareMail = (students: Student[], team: Omit) => {
diff --git a/src/lib/server/schema.ts b/src/lib/server/schema.ts
index a4b01f1..dacb917 100644
--- a/src/lib/server/schema.ts
+++ b/src/lib/server/schema.ts
@@ -52,24 +52,24 @@ const StudentSchema = z.object({
student_certificate: z.string().min(1)
});
-const MAX_FILE_SIZE = 5242880;
+const MAX_FILE_SIZE = 10485760;
const StudentFileSchema = z.object({
image: z
.instanceof(File)
- .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 5MB.')
+ .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 10MB.')
.refine((file) => file?.type === 'application/pdf', 'Only .pdf formats are supported.'),
citizen_card: z
.instanceof(File)
- .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 5MB.')
+ .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 10MB.')
.refine((file) => file?.type === 'application/pdf', 'Only .pdf formats are supported.'),
student_card: z
.instanceof(File)
- .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 5MB.')
+ .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 10MB.')
.refine((file) => file?.type === 'application/pdf', 'Only .pdf formats are supported.'),
student_certificate: z
.instanceof(File)
- .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 5MB.')
+ .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 10MB.')
.refine((file) => file?.type === 'application/pdf', 'Only .pdf formats are supported.')
});
@@ -99,11 +99,11 @@ const TeamSchema = z.object({
const TeamFileSchema = z.object({
teacher_citizen_card: z
.instanceof(File)
- .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 5MB.')
+ .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 10MB.')
.refine((file) => file?.type === 'application/pdf', 'Only .pdf formats are supported.'),
teacher_verify: z
.instanceof(File)
- .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 5MB.')
+ .refine((file) => file?.size <= MAX_FILE_SIZE, 'Max image size is 10MB.')
.refine((file) => file?.type === 'application/pdf', 'Only .pdf formats are supported.'),
students: z.array(StudentFileSchema).min(2).max(3)
});
diff --git a/src/lib/stores/consent.ts b/src/lib/stores/consent.ts
index a37807c..12be946 100644
--- a/src/lib/stores/consent.ts
+++ b/src/lib/stores/consent.ts
@@ -1,6 +1,6 @@
-import {writable} from 'svelte/store';
+import { writable } from 'svelte/store';
const consent = writable(false);
const verify = writable(false);
-export {consent, verify}
\ No newline at end of file
+export { consent, verify };
diff --git a/src/lib/stores/form.ts b/src/lib/stores/form.ts
index 652df4e..d6ad0d0 100644
--- a/src/lib/stores/form.ts
+++ b/src/lib/stores/form.ts
@@ -114,8 +114,5 @@ const stored =
: null;
const formContent = writable(stored || defaultValue);
-formContent.subscribe((value) => {
- if (browser) window.localStorage.form = JSON.stringify(value);
-});
export { formContent };
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 17abf18..bbd2774 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,5 +1,18 @@
-
-
+{#key data.url}
+
+
+
+{/key}
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts
new file mode 100644
index 0000000..d2a5d99
--- /dev/null
+++ b/src/routes/+layout.ts
@@ -0,0 +1,7 @@
+import type { LayoutLoad } from './$types';
+
+export const load: LayoutLoad = ({ url }) => {
+ return {
+ url: url.pathname
+ };
+};
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index f1c1444..c59d521 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,8 +1,147 @@
-
-
-
Bangmod Hackathon 2024
-
- Welcome to Bangmod Hackathon 2024
-
-
+
+
+
+ Bangmod Hackathon 2024
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/routes/+page.ts b/src/routes/+page.ts
new file mode 100644
index 0000000..189f71e
--- /dev/null
+++ b/src/routes/+page.ts
@@ -0,0 +1 @@
+export const prerender = true;
diff --git a/src/routes/policies/+page.svelte b/src/routes/policies/+page.svelte
index 7e616bf..9f4343c 100644
--- a/src/routes/policies/+page.svelte
+++ b/src/routes/policies/+page.svelte
@@ -64,17 +64,19 @@
Privacy Policies
{#each policies as policy}
-
+
{policy.name}
@@ -94,15 +96,15 @@
-
+
{/each}
diff --git a/src/routes/policies/+page.ts b/src/routes/policies/+page.ts
new file mode 100644
index 0000000..fb72c23
--- /dev/null
+++ b/src/routes/policies/+page.ts
@@ -0,0 +1,14 @@
+import { redirect } from '@sveltejs/kit';
+
+import type { PageLoad } from './$types';
+
+import { PUBLIC_CLOSING_DATE } from '$env/static/public';
+
+export const load: PageLoad = () => {
+ const currentDate = new Date();
+ const deadline = new Date(PUBLIC_CLOSING_DATE);
+ if (currentDate >= deadline) {
+ throw redirect(302, '/');
+ }
+ return {};
+};
diff --git a/src/routes/register/+page.server.ts b/src/routes/register/+page.server.ts
index 13ede35..0b8a7cd 100644
--- a/src/routes/register/+page.server.ts
+++ b/src/routes/register/+page.server.ts
@@ -3,14 +3,23 @@ import { superValidate } from 'sveltekit-superforms/server';
import { prepareMail, sendEmail } from '$lib/server/email';
import { deserializeNested, prepareData } from '$lib/server/form';
-import { TeamSchema } from '$lib/server/schema';
+import { TeamFileSchema, TeamSchema } from '$lib/server/schema';
import type { Team, TeamFile } from '$lib/server/schema';
import { UploadFile } from '$lib/server/storage';
import { supabase } from '$lib/server/supabase';
import type { Actions, PageServerLoad } from './$types';
+import { PUBLIC_CLOSING_DATE } from '$env/static/public';
+
export const load: PageServerLoad = async ({ url }) => {
+ const currentDate = new Date();
+ const deadline = new Date(PUBLIC_CLOSING_DATE);
+
+ if (currentDate >= deadline) {
+ throw redirect(302, '/');
+ }
+
const consent = url.searchParams.get('consent');
const verify = url.searchParams.get('verify');
if (!consent || !verify) {
@@ -24,6 +33,13 @@ export const load: PageServerLoad = async ({ url }) => {
export const actions: Actions = {
default: async ({ request }) => {
+ const currentDate = new Date();
+ const deadline = new Date(PUBLIC_CLOSING_DATE);
+
+ if (currentDate >= deadline) {
+ throw redirect(302, '/');
+ }
+
const formData = await request.formData();
const { data, files } = deserializeNested(formData) as { data: Team; files: TeamFile };
@@ -32,23 +48,18 @@ export const actions: Actions = {
const form = await superValidate(data, TeamSchema);
if (!form.valid) {
- console.log(form.errors);
- return fail(400, { form, error: 'Form is not valid.\nSome input might be incorrect.' });
+ return fail(400, { form, error: 'ข้อมูลบางช่องอาจจะกรอกผิดหรือไม่ได้กรอก.' });
}
const teamId = crypto.randomUUID();
const { students, team } = prepareData(teamId, data, files);
- const { error: teamInsertError } = await supabase.from('team').insert(team);
- if (teamInsertError) {
- console.log(teamInsertError);
- return fail(500, { form, error: teamInsertError });
- }
-
- const { error: studentInsertError } = await supabase.from('student').insert(students);
- if (studentInsertError) {
- return fail(500, { form, error: studentInsertError });
+ try {
+ TeamFileSchema.parse(files);
+ } catch (error) {
+ console.log(error);
+ return fail(501, { form, error: 'ระบบรองรับไฟล์ PDF ขนาดไม่เกิน 5 MB เท่านั้น' });
}
const uploadPromise: Promise
[] = [
@@ -67,23 +78,38 @@ export const actions: Actions = {
try {
await Promise.all(uploadPromise);
- await sendEmail(prepareMail(students, team), [
- {
- name: `${team.teacher_prefix}${team.teacher_firstname} ${team.teacher_lastname}`,
- email: team.teacher_email
- },
- ...students.map((student) => {
- return {
- name: `${student.name_prefix}${student.firstname} ${student.lastname}`,
- email: student.email
- };
- })
- ]);
} catch (error) {
console.log(error);
- return fail(501, { form, error: error });
+ return fail(501, { form, error: `Upload file error ${JSON.stringify(error)}` });
+ }
+
+ const { error: teamInsertError } = await supabase.from('team').insert(team);
+ if (teamInsertError) {
+ console.log(teamInsertError);
+ return fail(500, { form, error: `Database Insert error ${JSON.stringify(teamInsertError)}` });
+ }
+
+ const { error: studentInsertError } = await supabase.from('student').insert(students);
+ if (studentInsertError) {
+ return fail(500, {
+ form,
+ error: `Database Insert error ${JSON.stringify(studentInsertError)}`
+ });
}
- throw redirect(302, '/register/completed');
+ await sendEmail(prepareMail(students, team), [
+ {
+ name: `${team.teacher_prefix}${team.teacher_firstname} ${team.teacher_lastname}`,
+ email: team.teacher_email
+ },
+ ...students.map((student) => {
+ return {
+ name: `${student.name_prefix}${student.firstname} ${student.lastname}`,
+ email: student.email
+ };
+ })
+ ]);
+
+ return { form };
}
};
diff --git a/src/routes/register/+page.svelte b/src/routes/register/+page.svelte
index d376db2..a894099 100644
--- a/src/routes/register/+page.svelte
+++ b/src/routes/register/+page.svelte
@@ -17,17 +17,20 @@
import type { ActionData, PageData } from './$types';
import { browser } from '$app/environment';
+ import { goto } from '$app/navigation';
$: if (browser) window.localStorage.form = JSON.stringify($formContent);
let student_number = 2;
- let submitting = false;
export let data: PageData;
- const { enhance, errors } = superForm(data.form, {
- onSubmit: () => (submitting = true),
- onResult: () => (submitting = false)
+ const { enhance, errors, delayed } = superForm(data.form, {
+ onResult({result}) {
+ if (result.type === 'success') {
+ setTimeout(() => goto('/register/completed'), 50);
+ }
+ }
});
const teacherNamePrefixItems = ['นาย', 'นาง', 'นางสาว'];
@@ -46,55 +49,65 @@
let errorModal: boolean;
- $: errorModal = (form && form.error) as boolean;
+ $: errorModal = (form && form.error != null) as boolean;
- Register
+ Register - Bangmod Hackathon 2024