diff --git a/app/signup/page.tsx b/app/signup/page.tsx index 09f3968..75c5fb0 100644 --- a/app/signup/page.tsx +++ b/app/signup/page.tsx @@ -107,12 +107,26 @@ export default function SignupPage() { if (authError) { setError(authError.message); setLoading(false); return } + // If Supabase returns a session immediately it means email confirmation is + // disabled — the user is fully signed up AND signed in in one step. + // We still need to create the space/member record via the server action. if (authData.session) { + // User is now authenticated — create the space or join via server action + const result = mode === 'create' + ? await createSpace({ spaceName, spaceSlug, spaceCity, displayName: fullName }) + : await joinSpace({ inviteCode, displayName: fullName }) + + if (result.error) { + setError(result.error) + setLoading(false) + return + } router.push('/dashboard') router.refresh() return } + // Email confirmation is required — redirect to the confirm page router.push('/signup/confirm?email=' + encodeURIComponent(email)) } diff --git a/scripts/schema.sql b/scripts/schema.sql index 820fc18..0cfff86 100644 --- a/scripts/schema.sql +++ b/scripts/schema.sql @@ -145,38 +145,44 @@ $$; -- ── spaces ─────────────────────────────────────────────────────────────────── -- Top-level tenant. Each hackerspace is one row. CREATE TABLE IF NOT EXISTS public.spaces ( - id uuid PRIMARY KEY DEFAULT uuid_generate_v4(), - name text NOT NULL, - slug text NOT NULL UNIQUE, - city text, - require_approval boolean NOT NULL DEFAULT true, - public_member_directory boolean NOT NULL DEFAULT false, - invite_code text NOT NULL UNIQUE, - webhook_secret text, - created_at timestamptz NOT NULL DEFAULT now(), - updated_at timestamptz NOT NULL DEFAULT now() + id uuid PRIMARY KEY DEFAULT uuid_generate_v4(), + name text NOT NULL, + slug text NOT NULL UNIQUE, + description text, + logo_url text, + city text, + address text, + timezone text DEFAULT 'America/Phoenix', + invite_code text, + require_approval boolean NOT NULL DEFAULT true, + public_member_directory boolean NOT NULL DEFAULT false, + webhook_secret text, + settings jsonb DEFAULT '{}', + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now() ); -- ── space_members ───────────────────────────────────────────────────────────── -- One row per (user × space). A user may belong to multiple spaces. CREATE TABLE IF NOT EXISTS public.space_members ( - id uuid PRIMARY KEY DEFAULT uuid_generate_v4(), - space_id uuid NOT NULL REFERENCES public.spaces(id) ON DELETE CASCADE, - user_id uuid REFERENCES auth.users(id) ON DELETE SET NULL, - display_name text NOT NULL, - handle text, - email text, - phone text, - role member_role NOT NULL DEFAULT 'member', - tier member_tier NOT NULL DEFAULT 'basic', - status member_status NOT NULL DEFAULT 'current', - approved boolean NOT NULL DEFAULT true, - has_card_access boolean NOT NULL DEFAULT false, - payment_status text, - payment_note text, - last_payment_at timestamptz, - last_paid_at timestamptz, - joined_at timestamptz NOT NULL DEFAULT now() + id uuid PRIMARY KEY DEFAULT uuid_generate_v4(), + space_id uuid NOT NULL REFERENCES public.spaces(id) ON DELETE CASCADE, + user_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, + role public.member_role NOT NULL DEFAULT 'member', + tier public.member_tier NOT NULL DEFAULT 'basic', + status public.member_status NOT NULL DEFAULT 'unverified', + approved boolean NOT NULL DEFAULT true, + full_name text, + email text, + phone text, + bio text, + avatar_url text, + joined_at timestamptz DEFAULT now(), + dues_paid_until timestamptz, + stripe_customer_id text, + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now(), + UNIQUE (space_id, user_id) ); -- ── tasks ────────────────────────────────────────────────────────────────────