mirror of
https://github.com/MAGICGrants/campaign-site.git
synced 2026-01-09 12:27:59 -05:00
feat: open register modal when clicking membership button while logged out
This commit is contained in:
@@ -69,6 +69,7 @@ const Header = () => {
|
||||
<DialogContent>
|
||||
<LoginFormModal
|
||||
close={() => setLoginIsOpen(false)}
|
||||
openRegisterModal={() => setRegisterIsOpen(true)}
|
||||
openPasswordResetModal={() => setPasswordResetIsOpen(true)}
|
||||
/>
|
||||
</DialogContent>
|
||||
@@ -79,7 +80,10 @@ const Header = () => {
|
||||
<Button className="w-24">Register</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<RegisterFormModal close={() => setRegisterIsOpen(false)} />
|
||||
<RegisterFormModal
|
||||
close={() => setRegisterIsOpen(false)}
|
||||
openLoginModal={() => setLoginIsOpen(true)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
|
||||
@@ -6,21 +6,9 @@ import { signIn, useSession } from 'next-auth/react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { z } from 'zod'
|
||||
|
||||
import {
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from './ui/dialog'
|
||||
import { DialogContent, DialogDescription, DialogHeader, DialogTitle } from './ui/dialog'
|
||||
import { Input } from './ui/input'
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from './ui/form'
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from './ui/form'
|
||||
import { Button } from './ui/button'
|
||||
import { useToast } from './ui/use-toast'
|
||||
|
||||
@@ -31,9 +19,13 @@ const schema = z.object({
|
||||
|
||||
type LoginFormInputs = z.infer<typeof schema>
|
||||
|
||||
type Props = { close: () => void; openPasswordResetModal: () => void }
|
||||
type Props = {
|
||||
close: () => void
|
||||
openPasswordResetModal: () => void
|
||||
openRegisterModal: () => void
|
||||
}
|
||||
|
||||
function LoginFormModal({ close, openPasswordResetModal }: Props) {
|
||||
function LoginFormModal({ close, openPasswordResetModal, openRegisterModal }: Props) {
|
||||
const { toast } = useToast()
|
||||
const router = useRouter()
|
||||
const form = useForm<LoginFormInputs>({
|
||||
@@ -79,11 +71,6 @@ function LoginFormModal({ close, openPasswordResetModal }: Props) {
|
||||
close()
|
||||
}
|
||||
|
||||
function onIForgotMyPassword() {
|
||||
close()
|
||||
openPasswordResetModal()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<DialogHeader>
|
||||
@@ -92,10 +79,7 @@ function LoginFormModal({ close, openPasswordResetModal }: Props) {
|
||||
</DialogHeader>
|
||||
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="flex flex-col space-y-4"
|
||||
>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col space-y-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="email"
|
||||
@@ -127,7 +111,7 @@ function LoginFormModal({ close, openPasswordResetModal }: Props) {
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onIForgotMyPassword}
|
||||
onClick={() => (openPasswordResetModal(), close())}
|
||||
variant="link"
|
||||
className="self-end"
|
||||
>
|
||||
@@ -135,12 +119,21 @@ function LoginFormModal({ close, openPasswordResetModal }: Props) {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Button type="submit" disabled={form.formState.isSubmitting}>
|
||||
{form.formState.isSubmitting && (
|
||||
<ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
|
||||
)}{' '}
|
||||
Login
|
||||
</Button>
|
||||
<div className="flex flex-row space-x-2">
|
||||
<Button
|
||||
className="grow basis-0"
|
||||
variant="outline"
|
||||
type="button"
|
||||
onClick={() => (openRegisterModal(), close())}
|
||||
>
|
||||
Register
|
||||
</Button>
|
||||
|
||||
<Button className="grow basis-0" type="submit" disabled={form.formState.isSubmitting}>
|
||||
{form.formState.isSubmitting && <ReloadIcon className="mr-2 h-4 w-4 animate-spin" />}{' '}
|
||||
Login
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
|
||||
@@ -39,9 +39,9 @@ const schema = z
|
||||
|
||||
type RegisterFormInputs = z.infer<typeof schema>
|
||||
|
||||
type Props = { close: () => void }
|
||||
type Props = { close: () => void; openLoginModal: () => void }
|
||||
|
||||
function RegisterFormModal({ close }: Props) {
|
||||
function RegisterFormModal({ close, openLoginModal }: Props) {
|
||||
const { toast } = useToast()
|
||||
const form = useForm<RegisterFormInputs>({ resolver: zodResolver(schema) })
|
||||
const registerMutation = trpc.auth.register.useMutation()
|
||||
@@ -59,11 +59,7 @@ function RegisterFormModal({ close }: Props) {
|
||||
const errorMessage = (error as any).message
|
||||
|
||||
if (errorMessage === 'EMAIL_TAKEN') {
|
||||
return form.setError(
|
||||
'email',
|
||||
{ message: 'Email is already taken.' },
|
||||
{ shouldFocus: true }
|
||||
)
|
||||
return form.setError('email', { message: 'Email is already taken.' }, { shouldFocus: true })
|
||||
}
|
||||
|
||||
toast({
|
||||
@@ -77,16 +73,11 @@ function RegisterFormModal({ close }: Props) {
|
||||
<>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Register</DialogTitle>
|
||||
<DialogDescription>
|
||||
Start supporting Monero projects today!
|
||||
</DialogDescription>
|
||||
<DialogDescription>Start supporting Monero projects today!</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="flex flex-col space-y-4"
|
||||
>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col space-y-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="name"
|
||||
@@ -143,16 +134,26 @@ function RegisterFormModal({ close }: Props) {
|
||||
)}
|
||||
/>
|
||||
|
||||
<Button type="submit" disabled={form.formState.isSubmitting}>
|
||||
{form.formState.isSubmitting && (
|
||||
<ReloadIcon className="mr-2 h-4 w-4 animate-spin" />
|
||||
)}{' '}
|
||||
Register
|
||||
</Button>
|
||||
<div className="flex flex-row space-x-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="link"
|
||||
className="grow basis-0"
|
||||
onClick={() => (openLoginModal(), close())}
|
||||
>
|
||||
I already have an account
|
||||
</Button>
|
||||
|
||||
<Button type="submit" disabled={form.formState.isSubmitting} className="grow basis-0">
|
||||
{form.formState.isSubmitting && <ReloadIcon className="mr-2 h-4 w-4 animate-spin" />}{' '}
|
||||
Register
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
)
|
||||
}
|
||||
1
|
||||
|
||||
export default RegisterFormModal
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import { useState } from 'react'
|
||||
import type { NextPage } from 'next'
|
||||
import Head from 'next/head'
|
||||
import { useState } from 'react'
|
||||
import ProjectList from '../components/ProjectList'
|
||||
import { useSession } from 'next-auth/react'
|
||||
|
||||
import { getAllPosts } from '../utils/md'
|
||||
import { ProjectItem } from '../utils/types'
|
||||
import Typing from '../components/Typing'
|
||||
import CustomLink from '../components/CustomLink'
|
||||
import { Button } from '../components/ui/button'
|
||||
import { Dialog, DialogContent } from '../components/ui/dialog'
|
||||
import { Dialog, DialogContent, DialogTrigger } from '../components/ui/dialog'
|
||||
import DonationFormModal from '../components/DonationFormModal'
|
||||
import MembershipFormModal from '../components/MembershipFormModal'
|
||||
import ProjectList from '../components/ProjectList'
|
||||
import LoginFormModal from '../components/LoginFormModal'
|
||||
import RegisterFormModal from '../components/RegisterFormModal'
|
||||
import PasswordResetFormModal from '../components/PasswordResetFormModal'
|
||||
|
||||
// These shouldn't be swept up in the regular list so we hardcode them
|
||||
const generalFund: ProjectItem = {
|
||||
@@ -29,6 +33,10 @@ const generalFund: ProjectItem = {
|
||||
const Home: NextPage<{ projects: any }> = ({ projects }) => {
|
||||
const [donateModalOpen, setDonateModalOpen] = useState(false)
|
||||
const [memberModalOpen, setMemberModalOpen] = useState(false)
|
||||
const [registerIsOpen, setRegisterIsOpen] = useState(false)
|
||||
const [loginIsOpen, setLoginIsOpen] = useState(false)
|
||||
const [passwordResetIsOpen, setPasswordResetIsOpen] = useState(false)
|
||||
const session = useSession()
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -58,7 +66,11 @@ const Home: NextPage<{ projects: any }> = ({ projects }) => {
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => setMemberModalOpen(true)}
|
||||
onClick={() =>
|
||||
session.status === 'authenticated'
|
||||
? setMemberModalOpen(true)
|
||||
: setRegisterIsOpen(true)
|
||||
}
|
||||
variant="outline"
|
||||
size="lg"
|
||||
className="px-14 font-semibold text-lg"
|
||||
@@ -111,6 +123,35 @@ const Home: NextPage<{ projects: any }> = ({ projects }) => {
|
||||
<MembershipFormModal project={generalFund} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{session.status !== 'authenticated' && (
|
||||
<>
|
||||
<Dialog open={loginIsOpen} onOpenChange={setLoginIsOpen}>
|
||||
<DialogContent>
|
||||
<LoginFormModal
|
||||
close={() => setLoginIsOpen(false)}
|
||||
openRegisterModal={() => setRegisterIsOpen(true)}
|
||||
openPasswordResetModal={() => setPasswordResetIsOpen(true)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Dialog open={registerIsOpen} onOpenChange={setRegisterIsOpen}>
|
||||
<DialogContent>
|
||||
<RegisterFormModal
|
||||
openLoginModal={() => setLoginIsOpen(true)}
|
||||
close={() => setRegisterIsOpen(false)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Dialog open={passwordResetIsOpen} onOpenChange={setPasswordResetIsOpen}>
|
||||
<DialogContent>
|
||||
<PasswordResetFormModal close={() => setPasswordResetIsOpen(false)} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
import { useState } from 'react'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { NextPage } from 'next/types'
|
||||
import Head from 'next/head'
|
||||
import ErrorPage from 'next/error'
|
||||
import Image from 'next/image'
|
||||
import xss from 'xss'
|
||||
|
||||
import { ProjectDonationStats, ProjectItem } from '../../utils/types'
|
||||
import { getProjectBySlug, getAllPosts } from '../../utils/md'
|
||||
import { getProjectBySlug } from '../../utils/md'
|
||||
import markdownToHtml from '../../utils/markdownToHtml'
|
||||
import {
|
||||
fetchPostJSON,
|
||||
fetchGetJSONAuthedBTCPay,
|
||||
fetchGetJSONAuthedStripe,
|
||||
} from '../../utils/api-helpers'
|
||||
import PageHeading from '../../components/PageHeading'
|
||||
import SocialIcon from '../../components/social-icons'
|
||||
import Progress from '../../components/Progress'
|
||||
import { prisma } from '../../server/services'
|
||||
import { Button } from '../../components/ui/button'
|
||||
import { Dialog, DialogContent } from '../../components/ui/dialog'
|
||||
import DonationFormModal from '../../components/DonationFormModal'
|
||||
import MembershipFormModal from '../../components/MembershipFormModal'
|
||||
import Head from 'next/head'
|
||||
import LoginFormModal from '../../components/LoginFormModal'
|
||||
import RegisterFormModal from '../../components/RegisterFormModal'
|
||||
import PasswordResetFormModal from '../../components/PasswordResetFormModal'
|
||||
|
||||
type SingleProjectPageProps = {
|
||||
project: ProjectItem
|
||||
@@ -31,9 +29,12 @@ type SingleProjectPageProps = {
|
||||
|
||||
const Project: NextPage<SingleProjectPageProps> = ({ project, projects, donationStats }) => {
|
||||
const router = useRouter()
|
||||
|
||||
const [donateModalOpen, setDonateModalOpen] = useState(false)
|
||||
const [memberModalOpen, setMemberModalOpen] = useState(false)
|
||||
const [registerIsOpen, setRegisterIsOpen] = useState(false)
|
||||
const [loginIsOpen, setLoginIsOpen] = useState(false)
|
||||
const [passwordResetIsOpen, setPasswordResetIsOpen] = useState(false)
|
||||
const session = useSession()
|
||||
|
||||
const {
|
||||
slug,
|
||||
@@ -53,7 +54,7 @@ const Project: NextPage<SingleProjectPageProps> = ({ project, projects, donation
|
||||
|
||||
function formatBtc(bitcoin: number) {
|
||||
if (bitcoin > 0.1) {
|
||||
return `₿ ${bitcoin.toFixed(3) || 0.0}`
|
||||
return `${bitcoin.toFixed(3) || 0.0} BTC`
|
||||
} else {
|
||||
return `${Math.floor(bitcoin * 100000000).toLocaleString()} sats`
|
||||
}
|
||||
@@ -94,7 +95,14 @@ const Project: NextPage<SingleProjectPageProps> = ({ project, projects, donation
|
||||
{!project.isFunded && (
|
||||
<div className="flex flex-col space-y-2">
|
||||
<Button onClick={() => setDonateModalOpen(true)}>Donate</Button>
|
||||
<Button onClick={() => setMemberModalOpen(true)} variant="outline">
|
||||
<Button
|
||||
onClick={() =>
|
||||
session.status === 'authenticated'
|
||||
? setMemberModalOpen(true)
|
||||
: setRegisterIsOpen(true)
|
||||
}
|
||||
variant="outline"
|
||||
>
|
||||
Get Annual Membership
|
||||
</Button>
|
||||
</div>
|
||||
@@ -127,7 +135,7 @@ const Project: NextPage<SingleProjectPageProps> = ({ project, projects, donation
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
{donationStats.btc.amount} BTC{' '}
|
||||
{formatBtc(donationStats.btc.amount)}{' '}
|
||||
<span className="font-normal text-sm text-gray">
|
||||
in {donationStats.btc.count} donations
|
||||
</span>
|
||||
@@ -160,6 +168,35 @@ const Project: NextPage<SingleProjectPageProps> = ({ project, projects, donation
|
||||
<MembershipFormModal project={project} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{session.status !== 'authenticated' && (
|
||||
<>
|
||||
<Dialog open={loginIsOpen} onOpenChange={setLoginIsOpen}>
|
||||
<DialogContent>
|
||||
<LoginFormModal
|
||||
close={() => setLoginIsOpen(false)}
|
||||
openRegisterModal={() => setRegisterIsOpen(true)}
|
||||
openPasswordResetModal={() => setPasswordResetIsOpen(true)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Dialog open={registerIsOpen} onOpenChange={setRegisterIsOpen}>
|
||||
<DialogContent>
|
||||
<RegisterFormModal
|
||||
openLoginModal={() => setLoginIsOpen(true)}
|
||||
close={() => setRegisterIsOpen(false)}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Dialog open={passwordResetIsOpen} onOpenChange={setPasswordResetIsOpen}>
|
||||
<DialogContent>
|
||||
<PasswordResetFormModal close={() => setPasswordResetIsOpen(false)} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user