-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
240 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
NEXTAUTH_URL=http://localhost:3000 | ||
NEXTAUTH_SECRET=topsecret | ||
NEXTAUTH_URL=http://localhost:3000 | ||
|
||
# --- Start for development | ||
POSTGRES_DB=postgres | ||
|
@@ -17,13 +17,11 @@ DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:${POSTG | |
# GITHUB_ORG= | ||
|
||
# Use this one for magic link authentication | ||
SMTP_USER=mailpit | ||
SMTP_PASSWORD=topsecret | ||
SMTP_HOST=0.0.0.0 | ||
SMTP_PORT=1025 | ||
EMAIL_FROM="Sieutoc Team <[email protected]>" | ||
# SMTP_USER=mailpit | ||
# SMTP_PASSWORD=topsecret | ||
# SMTP_HOST=0.0.0.0 | ||
# SMTP_PORT=1025 | ||
# EMAIL_FROM="Sieutoc Team <[email protected]>" | ||
|
||
EASYPANEL_API_KEY= | ||
EASYPANEL_URL= | ||
|
||
STRIPE_SECRET_KEY= | ||
EASYPANEL_API_KEY= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
'use client'; | ||
|
||
import { | ||
ButtonProps, | ||
Button, | ||
ModalCloseButton, | ||
ModalContent, | ||
ModalOverlay, | ||
ModalHeader, | ||
ModalBody, | ||
Modal, | ||
Stack, | ||
Heading, | ||
Text, | ||
ModalFooter, | ||
ListItem, | ||
List, | ||
ListIcon, | ||
Badge, | ||
Flex, | ||
} from '@/components/chakra'; | ||
import { CheckIcon, PremiumIcon } from '@/icons'; | ||
import { forwardRef, useState } from 'react'; | ||
import { FEATURES } from '@/lib/constants'; | ||
import { useDisclosure } from '@/hooks'; | ||
|
||
export type ProButtonProps = ButtonProps; | ||
|
||
export const ProButton = forwardRef<HTMLButtonElement, ProButtonProps>((props, ref) => { | ||
const { isOpen, onOpen, onClose } = useDisclosure(); | ||
const [isYearly, setYearly] = useState(true); | ||
|
||
const billMode = isYearly ? 'yearly' : 'monthly'; | ||
|
||
return ( | ||
<> | ||
<Button ref={ref} leftIcon={<PremiumIcon />} onClick={onOpen} {...props} /> | ||
<Modal size="lg" isOpen={isOpen} onClose={onClose}> | ||
<ModalOverlay /> | ||
<ModalContent as={Stack} spacing={2}> | ||
<ModalHeader> | ||
<PremiumIcon /> Pika Pro | ||
</ModalHeader> | ||
<ModalCloseButton /> | ||
<ModalBody as={Stack} spacing={6}> | ||
<Flex justify="space-between" align="center"> | ||
<Heading size="md" textAlign="start"> | ||
Billed {billMode} | ||
<Badge | ||
py={1} | ||
px={2} | ||
marginLeft={2} | ||
marginBottom={1} | ||
fontSize="0.9em" | ||
variant="outline" | ||
borderRadius="lg" | ||
colorScheme="green" | ||
textTransform="lowercase" | ||
> | ||
${FEATURES['PRO'].price[billMode]}/month | ||
</Badge> | ||
</Heading> | ||
|
||
<Button size="xs" variant="ghost" onClick={() => setYearly(!isYearly)}> | ||
Switch to {isYearly ? 'monthly' : 'yearly'} | ||
</Button> | ||
</Flex> | ||
<List spacing={1}> | ||
{FEATURES['PRO'].features.map((feature, index) => ( | ||
<ListItem key={`feature-${index}`}> | ||
<Stack direction="row" align="flex-start" spacing={1}> | ||
<ListIcon as={CheckIcon} color="brand.500" boxSize={2} mt={2} /> | ||
<Text>{feature}</Text> | ||
</Stack> | ||
</ListItem> | ||
))} | ||
</List> | ||
</ModalBody> | ||
|
||
<ModalFooter as={Stack} spacing={6}> | ||
<Button size="lg" colorScheme="brand" onClick={onClose}> | ||
Upgrade to Pro (billed {billMode}) | ||
</Button> | ||
|
||
<Button size="xs" variant="link" onClick={onClose}> | ||
Compare plans | ||
</Button> | ||
</ModalFooter> | ||
</ModalContent> | ||
</Modal> | ||
</> | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
'use client'; | ||
|
||
import { | ||
Button, | ||
FormControl, | ||
FormLabel, | ||
Heading, | ||
Input, | ||
SimpleGrid, | ||
Stack, | ||
Text, | ||
} from '@/components/chakra'; | ||
import { useColorModeValue, useState, useToast } from '@/hooks'; | ||
import { HttpMethod, SubscribeResponse } from '@/types'; | ||
import { NextLink } from '@/components/client'; | ||
import { fetcher } from '@/lib/utils'; | ||
|
||
export type SubscribeFormProps = { | ||
heading?: string; | ||
lists: number[]; | ||
}; | ||
|
||
export const SubscribeForm = ({ | ||
heading = 'Subscribe for updates', | ||
lists, | ||
}: SubscribeFormProps) => { | ||
const inputBgColor = useColorModeValue('gray.100', 'gray.800'); | ||
const [email, setEmail] = useState(''); | ||
const [name, setName] = useState(''); | ||
const { toast } = useToast(); | ||
|
||
const handleSubscribe = async () => { | ||
const response = await fetcher<SubscribeResponse>('/api/mailinglist/subscribers', { | ||
method: HttpMethod.POST, | ||
body: JSON.stringify({ | ||
name: name ? name : 'subscriber', | ||
status: 'enabled', | ||
lists, | ||
email, | ||
}), | ||
}); | ||
|
||
if (response.data) { | ||
toast({ description: 'Successfully subscribed! Please check your mailbox' }); | ||
} else { | ||
toast({ description: 'Something wrong, please contact support', status: 'error' }); | ||
} | ||
}; | ||
|
||
return ( | ||
<SimpleGrid | ||
minChildWidth="300px" | ||
alignItems="center" | ||
maxW="container.lg" | ||
spacingX={10} | ||
spacingY={10} | ||
my={8} | ||
> | ||
<Stack spacing={0}> | ||
<Heading as="h3" fontSize="3xl" fontWeight="bold"> | ||
{heading} | ||
</Heading> | ||
<Text fontSize="sm"> | ||
By subscribing, you agree with our{' '} | ||
<Button as={NextLink} size="sm" variant="link" href="/"> | ||
Terms | ||
</Button>{' '} | ||
and{' '} | ||
<Button as={NextLink} size="sm" variant="link" href="/"> | ||
Privacy Policy. | ||
</Button> | ||
</Text> | ||
</Stack> | ||
{name && ( | ||
<FormControl as={Stack} direction="row"> | ||
<FormLabel>Name</FormLabel> | ||
<Input | ||
onChange={(e) => setName(e.target.value)} | ||
focusBorderColor="brand.500" | ||
bgColor={inputBgColor} | ||
value={name} | ||
name="name" | ||
size="lg" | ||
/> | ||
</FormControl> | ||
)} | ||
<FormControl as={Stack} direction="row"> | ||
<FormLabel hidden>Subscribe</FormLabel> | ||
<Input | ||
onChange={(e) => setEmail(e.target.value)} | ||
focusBorderColor="brand.500" | ||
bgColor={inputBgColor} | ||
value={email} | ||
type="email" | ||
size="lg" | ||
/> | ||
<Button colorScheme="brand" size="lg" onClick={handleSubscribe}> | ||
Subscribe | ||
</Button> | ||
</FormControl> | ||
</SimpleGrid> | ||
); | ||
}; |