diff --git a/public/qrcode.png b/public/qrcode.png
new file mode 100644
index 0000000..6cf1f2f
Binary files /dev/null and b/public/qrcode.png differ
diff --git a/src/app/admin/signup/components/BackButton.tsx b/src/app/admin/signup/components/BackButton.tsx
new file mode 100644
index 0000000..9ebe018
--- /dev/null
+++ b/src/app/admin/signup/components/BackButton.tsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import { ChevronLeft } from 'lucide-react';
+
+export default function BackButton({ onBack }: { onBack: () => void }) {
+ return (
+
+ );
+}
diff --git a/src/app/admin/signup/components/ConnectingStep.tsx b/src/app/admin/signup/components/ConnectingStep.tsx
new file mode 100644
index 0000000..badd34e
--- /dev/null
+++ b/src/app/admin/signup/components/ConnectingStep.tsx
@@ -0,0 +1,45 @@
+import { SignInStep } from '@/lib/types';
+import React, { useEffect } from 'react';
+import WalletIcon from '@/components/svg/WalletIcon';
+
+interface Props {
+ onBack: () => void;
+ onStepChange: (step: SignInStep) => void;
+}
+
+
+export default function ConnectingStep({ onBack, onStepChange }: Props) {
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ onStepChange("signature");
+ }, 3000);
+
+ return () => clearTimeout(timer);
+ }, [onStepChange]);
+
+ return (
+
+
+
+
+
+
Connecting to Wallet...
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/app/admin/signup/components/EmailSignInStep.tsx b/src/app/admin/signup/components/EmailSignInStep.tsx
new file mode 100644
index 0000000..efa2fe4
--- /dev/null
+++ b/src/app/admin/signup/components/EmailSignInStep.tsx
@@ -0,0 +1,130 @@
+import React, { useState, } from "react";
+import { Eye, EyeOff, Lock } from "lucide-react";
+import BackButton from "./BackButton";
+import { SignInStep } from "@/lib/types";
+
+
+interface EmailSignInStepProps {
+ onBack: () => void;
+ onStepChange: (step: SignInStep) => void;
+}
+
+const emailRegex = /^[\w-.]+@([\w-]+\.)+[\w-]{2,}$/i;
+
+export default function EmailSignInStep({
+ onBack,
+ onStepChange,
+}: EmailSignInStepProps) {
+ const [showPassword, setShowPassword] = useState(false);
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+ const [emailError, setEmailError] = useState("");
+
+ const handleEmailChange = (e: React.ChangeEvent) => {
+ const value = e.target.value;
+ setEmail(value);
+ if (value.length === 0 || emailRegex.test(value)) {
+ setEmailError("");
+ } else {
+ setEmailError("Please enter a valid email address");
+ }
+ };
+
+ const handleSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ if (!emailRegex.test(email)) {
+ setEmailError("Please enter a valid email address");
+ return;
+ } else {
+ setEmailError("");
+ onStepChange("success");
+ }
+ };
+
+ return (
+
+
+
+
+
+ Welcome Back
+
+
+ Enter your registered email address and password
+
+
+
+
+
+ );
+}
diff --git a/src/app/admin/signup/components/QRCodeStep.tsx b/src/app/admin/signup/components/QRCodeStep.tsx
new file mode 100644
index 0000000..18526ce
--- /dev/null
+++ b/src/app/admin/signup/components/QRCodeStep.tsx
@@ -0,0 +1,50 @@
+import React from "react";
+import BackButton from "./BackButton";
+import { SignInStep } from "@/lib/types";
+
+interface QRCodeStepProps {
+ onBack: () => void;
+ onStepChange: (step: SignInStep) => void;
+}
+
+export default function QRCodeStep({ onBack, onStepChange }: QRCodeStepProps) {
+ return (
+
+
+
+
+
+
+
+
onStepChange("connecting")}
+ className="bg-gray-300 cursor-pointer rounded-lg w-fit text-[#454545] px-6 py-3 text-base text-center"
+ >
+ Website
+
+
+ Mobile App
+
+
+
+
+

+
+
+
+
+ Scan to connect and log-In with Braavos app
+
+
+
+ );
+}
diff --git a/src/app/admin/signup/components/SignatureStep.tsx b/src/app/admin/signup/components/SignatureStep.tsx
new file mode 100644
index 0000000..52200d6
--- /dev/null
+++ b/src/app/admin/signup/components/SignatureStep.tsx
@@ -0,0 +1,44 @@
+import { SignInStep } from "@/lib/types";
+import React, { useEffect } from "react";
+
+interface Props {
+ onBack: () => void;
+ onStepChange: (step: SignInStep) => void;
+}
+
+export default function SignatureStep({ onBack, onStepChange }: Props) {
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ onStepChange("success");
+ }, 3000);
+
+ return () => clearTimeout(timer);
+ }, [onStepChange]);
+
+ return (
+
+
+
+
+
+ Sign the message in your wallet
+
+ to confirm the authentication process
+
+
+
+
+
+ );
+}
diff --git a/src/app/admin/signup/components/SuccessStep.tsx b/src/app/admin/signup/components/SuccessStep.tsx
new file mode 100644
index 0000000..f55c109
--- /dev/null
+++ b/src/app/admin/signup/components/SuccessStep.tsx
@@ -0,0 +1,35 @@
+import React from "react";
+import CheckIcon from "@/components/svg/CheckIcon";
+
+interface SuccessStepProps {
+ onProceed: () => void;
+}
+
+export default function SuccessStep({
+ onProceed,
+}: SuccessStepProps) {
+ return (
+
+
+
+
+
+ Bravoos Wallet Connected
+
+
+
+
+
+ );
+}
diff --git a/src/app/admin/signup/components/WalletSelectionStep.tsx b/src/app/admin/signup/components/WalletSelectionStep.tsx
new file mode 100644
index 0000000..0cbe0f4
--- /dev/null
+++ b/src/app/admin/signup/components/WalletSelectionStep.tsx
@@ -0,0 +1,161 @@
+import React, { useState, useEffect } from "react";
+import { Wallet } from "lucide-react";
+import { SignInStep } from "@/lib/types";
+import BackButton from "./BackButton";
+import { useWalletContext } from "@/components/blockchain/WalletProvider";
+import { useConnect, useAccount, Connector } from "@starknet-react/core";
+import { StarknetkitConnector, useStarknetkitConnectModal } from "starknetkit";
+import { WebWalletConnector } from "starknetkit/webwallet";
+
+interface WalletSelectionStepProps {
+ onBack: () => void;
+ onStepChange: (step: SignInStep) => void;
+}
+
+
+
+export default function WalletSelectionStep({
+ onBack,
+ onStepChange,
+}: WalletSelectionStepProps) {
+ const [selectedWallet, setSelectedWallet] = useState(null);
+ const [isConnecting, setIsConnecting] = useState(false);
+ const [connectionError, setConnectionError] = useState("");
+
+ const { connect, connectors } = useConnect();
+ const { isConnected, address } = useAccount();
+ const { connectWallet } = useWalletContext();
+
+ // Customize WebWalletConnector with an icon
+ const customizedConnectors = connectors.map((connector) => {
+ if (connector instanceof WebWalletConnector) {
+ return new WebWalletConnector({});
+ }
+ return connector;
+ });
+
+ const { starknetkitConnectModal } = useStarknetkitConnectModal({
+ connectors: customizedConnectors as StarknetkitConnector[],
+ });
+
+ const handleWalletConnect = async (connector: Connector) => {
+ try {
+ setIsConnecting(true);
+ setConnectionError("");
+ setSelectedWallet(connector.id);
+
+ await connect({ connector });
+
+ // Wait a bit for connection to establish
+ setTimeout(() => {
+ if (isConnected) {
+ onStepChange("success");
+ }
+ }, 1000);
+ } catch (error) {
+ console.error("Connection failed:", error);
+ setConnectionError("Failed to connect wallet. Please try again.");
+ setSelectedWallet(null);
+ } finally {
+ setIsConnecting(false);
+ }
+ };
+
+ const handleStarknetkitConnect = async () => {
+ try {
+ setIsConnecting(true);
+ setConnectionError("");
+
+ const { connector } = await starknetkitConnectModal();
+ if (connector) {
+ await connect({ connector: connector as Connector });
+ setTimeout(() => {
+ if (isConnected) {
+ onStepChange("success");
+ }
+ }, 1000);
+ }
+ } catch (error) {
+ console.error("Connection failed:", error);
+ setConnectionError("Failed to connect wallet. Please try again.");
+ } finally {
+ setIsConnecting(false);
+ }
+ };
+
+ // // Check if already connected
+ // useEffect(() => {
+ // if (isConnected && address) {
+ // onStepChange("success");
+ // }
+ // }, [isConnected, address, onStepChange]);
+
+
+
+ return (
+
+
+
+
+
Welcome Back
+
+
+ Connect to your registered wallet address to sign in
+
+
+ {connectionError && (
+
+ )}
+
+
+ {/* Available Wallets */}
+
+ {connectors.map((connector) => (
+
+ ))}
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/admin/signup/page.tsx b/src/app/admin/signup/page.tsx
new file mode 100644
index 0000000..f8018b7
--- /dev/null
+++ b/src/app/admin/signup/page.tsx
@@ -0,0 +1,119 @@
+"use client";
+import React, { useState } from "react";
+import { LinkIcon } from "lucide-react";
+import GoogleIcon2 from "@/components/svg/GoogleIcon2";
+import dynamic from "next/dynamic";
+import { SignInStep } from "@/lib/types";
+import QRCodeStep from "./components/QRCodeStep";
+import ConnectingStep from "./components/ConnectingStep";
+import SignatureStep from "./components/SignatureStep";
+import SuccessStep from "./components/SuccessStep";
+
+const EmailSignInStep = dynamic(() => import("./components/EmailSignInStep"), {
+ ssr: false,
+});
+
+const WalletSelectionStep = dynamic(() => import("./components/WalletSelectionStep"), {
+ ssr: false,
+});
+
+function Stepper({
+ step,
+ onStepChange,
+}: {
+ step: SignInStep;
+ onStepChange: (step: SignInStep) => void;
+}) {
+ if (step === "emailSignIn") {
+ return (
+ onStepChange("adminSignIn")}
+ onStepChange={onStepChange}
+ />
+ );
+ }
+ if (step === "walletSelection") {
+ return (
+ onStepChange("emailSignIn")}
+ onStepChange={onStepChange}
+ />
+ );
+ }
+
+ if (step === "qrCode") {
+ return (
+ onStepChange("walletSelection")} onStepChange={onStepChange} />
+ );
+ }
+
+ if (step === "connecting") {
+ return (
+ onStepChange("walletSelection")}
+ onStepChange={onStepChange}
+ />
+ );
+ }
+
+ if (step === "signature") {
+ return (
+ onStepChange("walletSelection")}
+ onStepChange={onStepChange}
+ />
+ );
+ }
+
+ if (step === "success") {
+ return onStepChange("adminSignIn")} />;
+ }
+
+ return ;
+}
+
+function AdminSignIn({
+ onStepChange,
+}: {
+ onStepChange: (step: SignInStep) => void;
+}) {
+ return (
+
+
+
+ How would you like to sign-in
+
+
+
onStepChange("emailSignIn")}
+ >
+
+
+
+
+ Sign-In using email
+
+
+
onStepChange("walletSelection")}
+ >
+
+
+
+
+ Sign-In using wallet address
+
+
+
+
+
+ );
+}
+
+export default function AdminSignInPage() {
+ const [step, setStep] = useState("adminSignIn");
+ const handleStepChange = (newStep: SignInStep) => setStep(newStep);
+ return ;
+}
diff --git a/src/components/svg/CheckIcon.tsx b/src/components/svg/CheckIcon.tsx
new file mode 100644
index 0000000..5ccded2
--- /dev/null
+++ b/src/components/svg/CheckIcon.tsx
@@ -0,0 +1,18 @@
+import * as React from "react"
+import { SVGProps } from "react"
+
+const CheckIcon = (props: SVGProps) => (
+
+)
+
+export default CheckIcon
diff --git a/src/components/svg/GoogleIcon2.tsx b/src/components/svg/GoogleIcon2.tsx
new file mode 100644
index 0000000..2fb4762
--- /dev/null
+++ b/src/components/svg/GoogleIcon2.tsx
@@ -0,0 +1,17 @@
+import * as React from "react"
+import { SVGProps } from "react"
+const GoogleIcon2 = (props: SVGProps) => (
+
+)
+export default GoogleIcon2
diff --git a/src/components/svg/MetaMaskIcon.tsx b/src/components/svg/MetaMaskIcon.tsx
new file mode 100644
index 0000000..4102289
--- /dev/null
+++ b/src/components/svg/MetaMaskIcon.tsx
@@ -0,0 +1,20 @@
+import * as React from "react"
+import { SVGProps } from "react"
+
+const MetaMaskIcon = (props: SVGProps) => (
+
+)
+
+export default MetaMaskIcon
diff --git a/src/components/svg/WalletConnectIcon.tsx b/src/components/svg/WalletConnectIcon.tsx
new file mode 100644
index 0000000..dc53fb1
--- /dev/null
+++ b/src/components/svg/WalletConnectIcon.tsx
@@ -0,0 +1,20 @@
+import * as React from "react"
+import { SVGProps } from "react"
+
+const WalletConnectIcon = (props: SVGProps) => (
+
+)
+
+export default WalletConnectIcon
diff --git a/src/components/svg/WalletIcon.tsx b/src/components/svg/WalletIcon.tsx
new file mode 100644
index 0000000..bfe3109
--- /dev/null
+++ b/src/components/svg/WalletIcon.tsx
@@ -0,0 +1,19 @@
+import * as React from "react"
+import { SVGProps } from "react"
+
+const WalletIcon = (props: SVGProps) => (
+
+)
+
+export default WalletIcon
diff --git a/src/lib/types.ts b/src/lib/types.ts
index c271a1d..e5e6d46 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -2,8 +2,17 @@ export type ClubDetailsProps = {
id: string;
name: string;
isPublic: boolean;
- memberCount: number;
- sessionsInfo: string;
+ memberCount: number;
+ sessionsInfo: string;
unreadNotifications: number;
- authorAvatars: string[];
+ authorAvatars: string[];
};
+
+export type SignInStep =
+ | "adminSignIn"
+ | "emailSignIn"
+ | "walletSelection"
+ | "qrCode"
+ | "connecting"
+ | "signature"
+ | "success";