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} +
    +
  • {qualify}
  • +
+ {/each} +
+
+
+
+
+

+ เอกสารที่ใช้ในการรับสมัคร +

+
+
+
+
+ +
+
+

อาจารย์ที่ปรึกษา

+ {#each teacher_files as teacher_file} +
    +
  • {teacher_file}
  • +
+ {/each} +
+
+
+ +
+
+
+ +
+
+

นักเรียน

+ {#each student_files as student_file} +
    +
  • {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} +
+
+
+ + 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 @@ + + + + + + + ... BMH2024 - BMH2024 - BMH2024 - BMH2024 - BMH2024 - BMH2024 - BMH2024 ... + + + + + 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 + + + + + +
+ + + + + + + + +
+ + + +
+ ©2023 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}
- + ข้าพเจ้าได้อ่านเงื่อนไขและข้อกำหนดอย่างครบถ้วนแล้ว และยอมรับในเงื่อนไขและข้อกำหนดทั้งหมด - + ข้าพเจ้าขอยืนยันว่าข้อมูลที่ใช้ในการสมัครเป็นข้อมูลจริง
@@ -110,9 +112,13 @@
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

Registration

-
+
- รายละเอียดเกี่ยวกับทีม - + รายละเอียดเกี่ยวกับทีม + + ชื่อทีม -
- - โรงเรียน - - - จำนวนสมาชิก - + + โรงเรียน + +
+ จำนวนสมาชิก * + +
-
+
- ข้อมูลเกี่ยวกับที่ปรึกษา + + ข้อมูลเกี่ยวกับที่ปรึกษา +
- ที่อยู่ปัจจุบัน * + ที่อยู่ปัจจุบัน
@@ -197,13 +212,13 @@ > อาหารที่แพ้ / ประเภทอาหาร (เช่น มังสวิรัติ, ฮาลาล) - ยาที่แพ้ + + ยาที่แพ้ +
- โรคประจําตัว / วิธีปฐมพยาบาลเมื่อเกิดอาการ + + โรคประจําตัว / วิธีปฐมพยาบาลเมื่อเกิดอาการ +
เอกสารประกอบการสมัคร
1. บัตรประชาชนอาจารย์ที่ปรึกษาพร้อมเซ็นกํากับหรือบัตรประจําตัวคนที่ไม่ได้ถือสัญชาติไทย - (เฉพาะด้านหน้า) + (เฉพาะด้านหน้า) (PDF ขนาดน้อยกว่า 5 MB) 2. เอกสาร หรือหนังสือยืนยันสถานภาพการเป็นอาจารย์ประจําสถาบันการศึกษา (บัตรประจําตัวครูอาจารย์, บัตรข้าราชการครูและบุคลากรทางการศึกษา) + (PDF ขนาดน้อยกว่า 5 MB)
{#each { length: student_number } as _, idx} -
+
- + ข้อมูลเกี่ยวกับผู้เข้าแข่งขันท่านที่ {idx + 1}
@@ -250,6 +266,7 @@ name="students[{idx}].firstname" errors={$errors?.students?.[idx].firstname} bind:value={$formContent.students[idx].firstname} + placeholder="ขยัน" required > ชื่อจริง (ภาษาไทย) @@ -259,6 +276,7 @@ name="students[{idx}].lastname" errors={$errors?.students?.[idx]?.lastname} bind:value={$formContent.students[idx].lastname} + placeholder="หมั่นเพียร" required > นามสกุล (ภาษาไทย) @@ -267,6 +285,7 @@ name="students[{idx}].nickname" errors={$errors?.students?.[idx].nickname} bind:value={$formContent.students[idx].nickname} + placeholder="ขยัน" required > ชื่อเล่น @@ -286,6 +305,7 @@ name="students[{idx}].race" errors={$errors?.students?.[idx].race} bind:value={$formContent.students[idx].race} + placeholder="เชื้อชาติ" required > เชื้อชาติ @@ -294,6 +314,7 @@ name="students[{idx}].nationality" errors={$errors?.students?.[idx].nationality} bind:value={$formContent.students[idx].nationality} + placeholder="สัญชาติ" required > สัญชาติ @@ -302,6 +323,7 @@ name="students[{idx}].religion" errors={$errors?.students?.[idx].religion} bind:value={$formContent.students[idx].religion} + placeholder="ศาสนา" required > ศาสนา @@ -313,6 +335,7 @@ name="students[{idx}].phone" errors={$errors?.students?.[idx].phone} bind:value={$formContent.students[idx].phone} + placeholder="0999999999" required > เบอร์โทรศัพท์ @@ -333,6 +356,7 @@ name="students[{idx}].email" errors={$errors?.students?.[idx].email} bind:value={$formContent.students[idx].email} + placeholder="khayan@mail.com" required > อีเมล @@ -351,6 +375,7 @@ name="students[{idx}].address" errors={$errors?.students?.[idx].address} bind:value={$formContent.students[idx].address} + placeholder="" required > ที่อยู่ปัจจุบัน @@ -409,7 +434,9 @@ errors={$errors?.students?.[idx].image} required > - รูปถ่ายนักเรียนผู้เข้าแข่งขัน + รูปถ่ายนักเรียนผู้เข้าแข่งขัน (PDF ขนาดน้อยกว่า 5 MB)
  • @@ -420,7 +447,8 @@ required > บัตรประชาชนผู้เข้าแข่งขันพร้อมเซ็นกํากับ
    - หรือบัตรประจําตัวคนซึ่งไม่ได้ถือสัญชาติไทย (เฉพาะด้านหน้า) + หรือบัตรประจําตัวคนซึ่งไม่ได้ถือสัญชาติไทย (เฉพาะด้านหน้า)
    + (PDF ขนาดน้อยกว่า 5 MB)
  • @@ -430,7 +458,7 @@ errors={$errors?.students?.[idx].student_card} required > - บัตรนักเรียน + บัตรนักเรียน (PDF ขนาดน้อยกว่า 5 MB)
  • @@ -440,14 +468,16 @@ errors={$errors?.students?.[idx].student_certificate} required > - ปพ.7 ของผู้เข้าแข่งขันตัวจริง + ปพ.7 ของผู้เข้าแข่งขันตัวจริง (PDF ขนาดน้อยกว่า 5 MB)
  • {/each} -
    +

    @@ -457,18 +487,18 @@

    ยินยอมการนําข้อมูลส่วนตัวไปใช้ - รับรองว่าข้อมูลทั้งหมดเป็นความจริง + + รับรองว่าข้อมูลทั้งหมดเป็นความจริง หากทีมงานตรวจสอบแล้วพบว่าข้อมูลไม่ตรงตามเงื่อนไขจะขอใช้อํานาจในการตัดสิทธิ์
    + {#if errorModal} -
    +
    -
    -

    An error occurred !

    +
    +

    มีข้อผิดพลาด !

    -
    -

    +

    +

    {form?.error}

    diff --git a/src/routes/register/completed/+page.svelte b/src/routes/register/completed/+page.svelte index cab8b49..741099a 100644 --- a/src/routes/register/completed/+page.svelte +++ b/src/routes/register/completed/+page.svelte @@ -1,13 +1,17 @@ + + Register Complete - Bangmod Hackathon 2024 + +
    -

    - Registration Complete -

    -
    - Facebook - Home -
    -
    \ No newline at end of file +

    + Registration Complete +

    +
    + Facebook + Home +
    +
    diff --git a/static/banner.webp b/static/banner.webp new file mode 100644 index 0000000..deb3cd6 Binary files /dev/null and b/static/banner.webp differ diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..c5bb38c Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/favicon.png b/static/favicon.png deleted file mode 100644 index 825b9e6..0000000 Binary files a/static/favicon.png and /dev/null differ diff --git a/static/favicon.webp b/static/favicon.webp new file mode 100644 index 0000000..cd1a0f0 Binary files /dev/null and b/static/favicon.webp differ diff --git a/svelte.config.js b/svelte.config.js index 226ac6b..b5f81f0 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -11,13 +11,7 @@ const config = { // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. // If your environment is not supported or you settled on a specific environment, switch out the adapter. // See https://kit.svelte.dev/docs/adapters for more information about adapters. - adapter: adapter({ - // See below for an explanation of these options - routes: { - include: ['/*'], - exclude: [''] - } - }) + adapter: adapter() } }; diff --git a/tailwind.config.js b/tailwind.config.js index e2cd7d3..c428b08 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -5,15 +5,26 @@ export default { content: ['./src/**/*.{html,js,svelte,ts}'], theme: { fontFamily: { - sans: ['Kanit', ...defaultTheme.fontFamily.sans], + sans: ['Maitree', ...defaultTheme.fontFamily.sans], serif: ['Old Standard TT', ...defaultTheme.fontFamily.serif], latin: ['Outfit'], - decorate: ['Homemade Apple'] + decorate: ['Homemade Apple'], + circle: ['Tenor Sans'], + mali: ['Mali'] }, extend: { colors: { soapstone: '#fefcfc', asphalt: '#0d0d02', + beer: '#febb28', + saddle: '#8a4b18', + butternut: '#fb7500', + lupine: '#ccaa4a', + sandy: '#FFE7BF', + burgundy: '#A10035', + aubergine: '#4A1727', + froly: '#FF869E', + eastbay: '#414C7D', iron: { 50: '#f6f6f7', 100: '#efeff0', @@ -54,21 +65,9 @@ export default { 950: '#52000c' } }, - animation: { - marquee: 'marquee 25s linear infinite', - marquee2: 'marquee2 25s linear infinite' - }, - keyframes: { - marquee: { - '0%': { transform: 'translateX(0%)' }, - '100%': { transform: 'translateX(-100%)' } - }, - marquee2: { - '0%': { transform: 'translateX(100%)' }, - '100%': { transform: 'translateX(0%)' } - } + gridTemplateColumns: { + 28: 'repeat(28, minmax(0, 1fr))' } } - }, - plugins: [] + } };