From c2353005e1be55f3bb53ae3dd2cc2a402fd3b57d Mon Sep 17 00:00:00 2001 From: Anthony Hayward Date: Wed, 16 Apr 2025 22:42:33 -0400 Subject: [PATCH 01/40] Style and UX overhaul --- db_migration.sql | 34 ++ package-lock.json | 254 +++++++++-- package.json | 8 +- src/App.tsx | 37 +- src/components/CreateClubModal.tsx | 232 +++++----- src/components/Layout.tsx | 90 +++- src/contexts/AuthContext.tsx | 85 ++++ src/main.tsx | 4 + src/pages/AttendEvent.tsx | 653 +++++++++++++++++++++++++++++ src/pages/ClubDetail.tsx | 601 ++++++++++++++++++++++++++ src/pages/ClubJoinQR.tsx | 114 +++++ src/pages/Clubs.tsx | 331 ++++++++++----- src/pages/JoinClub.tsx | 104 +++++ src/pages/JoinFlow.tsx | 314 ++++++++++++++ src/pages/Login.tsx | 157 +++++++ src/pages/Profile.tsx | 202 +++++++++ src/pages/Welcome.tsx | 118 ++++++ src/styles/designSystem.ts | 108 +++++ src/utils/dbMigrations.ts | 107 +++++ src/utils/supabaseClient.ts | 6 + tsconfig.app.tsbuildinfo | 2 +- 21 files changed, 3247 insertions(+), 314 deletions(-) create mode 100644 db_migration.sql create mode 100644 src/contexts/AuthContext.tsx create mode 100644 src/pages/AttendEvent.tsx create mode 100644 src/pages/ClubDetail.tsx create mode 100644 src/pages/ClubJoinQR.tsx create mode 100644 src/pages/JoinClub.tsx create mode 100644 src/pages/JoinFlow.tsx create mode 100644 src/pages/Login.tsx create mode 100644 src/pages/Profile.tsx create mode 100644 src/pages/Welcome.tsx create mode 100644 src/styles/designSystem.ts create mode 100644 src/utils/dbMigrations.ts create mode 100644 src/utils/supabaseClient.ts diff --git a/db_migration.sql b/db_migration.sql new file mode 100644 index 0000000..a807d6d --- /dev/null +++ b/db_migration.sql @@ -0,0 +1,34 @@ +-- Add UUID column to members table if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_name = 'members' AND column_name = 'member_uuid' + ) THEN + -- Add the UUID column + ALTER TABLE members ADD COLUMN member_uuid UUID; + + -- Generate UUIDs for existing members + UPDATE members SET member_uuid = gen_random_uuid() WHERE member_uuid IS NULL; + + -- Add a unique constraint to ensure all UUIDs are unique + ALTER TABLE members ADD CONSTRAINT members_member_uuid_unique UNIQUE (member_uuid); + END IF; +END $$; + +-- Add unique constraint combining club_id and name (if desired) +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 + FROM pg_constraint + WHERE conname = 'members_club_id_name_unique' + ) THEN + ALTER TABLE members ADD CONSTRAINT members_club_id_name_unique UNIQUE (club_id, name); + END IF; +EXCEPTION + -- Constraint might fail if there are duplicate names - handle gracefully + WHEN unique_violation THEN + RAISE NOTICE 'Could not add unique constraint - duplicate names exist in members table'; +END $$; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 5819de0..7dc322b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,15 +8,23 @@ "name": "vite-react", "version": "0.0.0", "dependencies": { - "framer-motion": "^12.7.3", + "@supabase/supabase-js": "^2.49.4", + "@types/react-csv": "^1.1.10", + "date-fns": "^4.1.0", + "framer-motion": "^10.16.4", + "qrcode.react": "^4.2.0", "react": "^18.3.1", + "react-csv": "^2.2.2", "react-dom": "^18.3.1", - "react-router-dom": "^7.5.0" + "react-icons": "^5.5.0", + "react-router-dom": "^7.5.0", + "uuid": "^11.1.0" }, "devDependencies": { "@eslint/js": "^9.9.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", + "@types/uuid": "^10.0.0", "@vitejs/plugin-react": "^4.3.1", "autoprefixer": "^10.4.16", "eslint": "^9.9.0", @@ -318,6 +326,21 @@ "node": ">=6.9.0" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -1269,6 +1292,73 @@ "win32" ] }, + "node_modules/@supabase/auth-js": { + "version": "2.69.1", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.69.1.tgz", + "integrity": "sha512-FILtt5WjCNzmReeRLq5wRs3iShwmnWgBvxHfqapC/VoljJl+W8hDAyFmf1NVw3zH+ZjZ05AKxiKxVeb0HNWRMQ==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/functions-js": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.4.tgz", + "integrity": "sha512-WL2p6r4AXNGwop7iwvul2BvOtuJ1YQy8EbOd0dhG1oN1q8el/BIRSFCFnWAMM/vJJlHWLi4ad22sKbKr9mvjoA==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/node-fetch": { + "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.19.4.tgz", + "integrity": "sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.11.2.tgz", + "integrity": "sha512-u/XeuL2Y0QEhXSoIPZZwR6wMXgB+RQbJzG9VErA3VghVt7uRfSVsjeqd7m5GhX3JR6dM/WRmLbVR8URpDWG4+w==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14", + "@types/phoenix": "^1.5.4", + "@types/ws": "^8.5.10", + "ws": "^8.18.0" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.7.1.tgz", + "integrity": "sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.49.4", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.49.4.tgz", + "integrity": "sha512-jUF0uRUmS8BKt37t01qaZ88H9yV1mbGYnqLeuFWLcdV+x1P4fl0yP9DGtaEhFPZcwSom7u16GkLEH9QJZOqOkw==", + "dependencies": { + "@supabase/auth-js": "2.69.1", + "@supabase/functions-js": "2.4.4", + "@supabase/node-fetch": "2.6.15", + "@supabase/postgrest-js": "1.19.4", + "@supabase/realtime-js": "2.11.2", + "@supabase/storage-js": "2.7.1" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1327,22 +1417,41 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/node": { + "version": "22.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", + "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/phoenix": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz", + "integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==" + }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", - "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", - "dev": true + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==" }, "node_modules/@types/react": { "version": "18.3.20", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz", "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==", - "dev": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" } }, + "node_modules/@types/react-csv": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@types/react-csv/-/react-csv-1.1.10.tgz", + "integrity": "sha512-PESAyASL7Nfi/IyBR3ufd8qZkyoS+7jOylKmJxRZUZLFASLo4NZaRsJ8rNP8pCcbIziADyWBbLPD1nPddhsL4g==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-dom": { "version": "18.3.6", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.6.tgz", @@ -1352,6 +1461,20 @@ "@types/react": "^18.0.0" } }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.30.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz", @@ -1949,8 +2072,16 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } }, "node_modules/debug": { "version": "4.4.0", @@ -2376,23 +2507,20 @@ } }, "node_modules/framer-motion": { - "version": "12.7.3", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.7.3.tgz", - "integrity": "sha512-dNT4l5gEnUo2ytXLUBUf6AI21dZ77TMclDKE3ElaIHZ8m90nJ/NCcExW51zdSIaS0RhAS5iXcF7bEIxZe8XG2g==", + "version": "10.16.4", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.16.4.tgz", + "integrity": "sha512-p9V9nGomS3m6/CALXqv6nFGMuFOxbWsmaOrdmhyQimMIlLl3LC7h7l86wge/Js/8cRu5ktutS/zlzgR7eBOtFA==", "dependencies": { - "motion-dom": "^12.7.3", - "motion-utils": "^12.7.2", "tslib": "^2.4.0" }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, "react": { "optional": true }, @@ -2838,19 +2966,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/motion-dom": { - "version": "12.7.3", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.7.3.tgz", - "integrity": "sha512-IjMt1YJHrvyvruFvmpmd6bGXXGCvmygrnvSb3aZ8KhOzF4H3PulU+cMBzH+U8TBJHjC/mnmJFRIA1Cu4vBfcBA==", - "dependencies": { - "motion-utils": "^12.7.2" - } - }, - "node_modules/motion-utils": { - "version": "12.7.2", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.7.2.tgz", - "integrity": "sha512-XhZwqctxyJs89oX00zn3OGCuIIpVevbTa+u82usWBC6pSHUd2AoNWiYa7Du8tJxJy9TFbZ82pcn5t7NOm1PHAw==" - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3254,6 +3369,14 @@ "node": ">=6" } }, + "node_modules/qrcode.react": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.2.0.tgz", + "integrity": "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3285,6 +3408,11 @@ "node": ">=0.10.0" } }, + "node_modules/react-csv": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/react-csv/-/react-csv-2.2.2.tgz", + "integrity": "sha512-RG5hOcZKZFigIGE8LxIEV/OgS1vigFQT4EkaHeKgyuCbUAu9Nbd/1RYq++bJcJJ9VOqO/n9TZRADsXNDR4VEpw==" + }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -3297,6 +3425,14 @@ "react": "^18.3.1" } }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", @@ -3754,6 +3890,11 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -3829,6 +3970,11 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -3874,6 +4020,18 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/vite": { "version": "5.4.18", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.18.tgz", @@ -3961,6 +4119,20 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4073,6 +4245,26 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index 2ffc233..df1ca95 100644 --- a/package.json +++ b/package.json @@ -10,15 +10,19 @@ "preview": "vite preview" }, "dependencies": { - "framer-motion": "^12.7.3", + "@supabase/supabase-js": "^2.49.4", + "framer-motion": "^10.16.4", + "qrcode.react": "^4.2.0", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-router-dom": "^7.5.0" + "react-router-dom": "^7.5.0", + "uuid": "^11.1.0" }, "devDependencies": { "@eslint/js": "^9.9.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", + "@types/uuid": "^10.0.0", "@vitejs/plugin-react": "^4.3.1", "autoprefixer": "^10.4.16", "eslint": "^9.9.0", diff --git a/src/App.tsx b/src/App.tsx index 1f90862..84c66f3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,17 +1,40 @@ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; -import Home from './pages/Home'; import Clubs from './pages/Clubs'; +import ClubDetail from './pages/ClubDetail'; +import ClubJoinQR from './pages/ClubJoinQR'; +import Login from './pages/Login'; +import Profile from './pages/Profile'; +import JoinClub from './pages/JoinClub'; +import JoinFlow from './pages/JoinFlow'; +import AttendEvent from './pages/AttendEvent'; +import Welcome from './pages/Welcome'; import './index.css'; +import { AuthProvider } from './contexts/AuthContext'; function App() { return ( - - } /> - } /> - {/* Add other routes as they are implemented */} - } /> - + + + {/* New welcome page as the main entry point */} + } /> + + {/* Club owner routes */} + } /> + } /> + } /> + } /> + } /> + + {/* Member routes */} + } /> + } /> + } /> + + {/* Fallback */} + } /> + + ); } diff --git a/src/components/CreateClubModal.tsx b/src/components/CreateClubModal.tsx index baf4932..3166fb1 100644 --- a/src/components/CreateClubModal.tsx +++ b/src/components/CreateClubModal.tsx @@ -24,31 +24,34 @@ const CATEGORIES = [ const overlayVariants = { hidden: { opacity: 0 }, - visible: { opacity: 1 } + visible: { + opacity: 1, + transition: { duration: 0.2 } + } }; const modalVariants = { hidden: { opacity: 0, - y: 50, - scale: 0.95 + y: 20, + scale: 0.98 }, visible: { opacity: 1, y: 0, scale: 1, transition: { - type: "spring", - stiffness: 300, - damping: 30 + type: "tween", + duration: 0.25, + ease: "easeOut" } }, exit: { opacity: 0, - y: 50, - scale: 0.95, + y: 20, + scale: 0.98, transition: { - duration: 0.2 + duration: 0.15 } } }; @@ -68,156 +71,115 @@ const CreateClubModal: React.FC = ({ e.preventDefault(); onSubmit(formData); setFormData({ name: '', description: '', category: '' }); - onClose(); + // Keep modal open logic handled by parent }; return ( {isOpen && ( e.stopPropagation()} // Prevent closing when clicking inside modal > -
- {/* Header */} -
-
- - Create New Club - - - - - - -
+ {/* Header */} +
+

+ Create New Club +

+ +
+ + {/* Form */} +
+
+ + setFormData({ ...formData, name: e.target.value })} + className="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-1 focus:ring-black focus:border-black bg-white" + placeholder="e.g., Chess Club" + required + />
- {/* Form */} - - + + setFormData({ ...formData, name: e.target.value })} - className="w-full px-4 py-3 rounded-xl bg-[#f5f5f7] border border-transparent - focus:outline-none focus:border-[#1d1d1f]/30 focus:bg-white - text-[#1d1d1f] placeholder-[#1d1d1f]/40 transition-all duration-200" - placeholder="Enter club name" - required - /> - + + {CATEGORIES.map(category => ( + + ))} + + {/* Add down arrow icon for select */} +
- - - - +
+ +