mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-09 07:25:19 +02:00
update and fix merge conflict
This commit is contained in:
commit
004a94f48e
10 changed files with 66 additions and 192 deletions
|
@ -21,8 +21,6 @@ NX_FINICITY_PARTNER_SECRET=
|
|||
NX_TELLER_SIGNING_SECRET=
|
||||
NX_TELLER_APP_ID=
|
||||
|
||||
NEXT_PUBLIC_ZAPIER_FEEDBACK_HOOK_URL=
|
||||
|
||||
# Email credentials
|
||||
NX_POSTMARK_FROM_ADDRESS=account@example.com
|
||||
NX_POSTMARK_REPLY_TO_ADDRESS=support@example.com
|
||||
|
|
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
19
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
19
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
|
@ -187,7 +187,9 @@ export default function AccountsSidebar() {
|
|||
label={title}
|
||||
balances={balances.data}
|
||||
inverted={classification === 'liability'}
|
||||
onToggle={(isExpanded) => updateToggleState(title, isExpanded)}
|
||||
onToggle={(isExpanded) =>
|
||||
updateToggleState(`${title}-${classification}`, isExpanded)
|
||||
}
|
||||
expanded={toggleState[title] !== false}
|
||||
level={1}
|
||||
syncing={items.some((a) => a.syncing)}
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
import Link from 'next/link'
|
||||
import { useUserApi } from '@maybe-finance/client/shared'
|
||||
import { Button } from '@maybe-finance/design-system'
|
||||
import toast from 'react-hot-toast'
|
||||
import { signOut } from 'next-auth/react'
|
||||
|
||||
export function CountryWaitlist({ country }: { country?: string }) {
|
||||
const { useDelete } = useUserApi()
|
||||
|
||||
const deleteUser = useDelete({
|
||||
onSuccess() {
|
||||
toast.success(`Account deleted`)
|
||||
setTimeout(() => signOut(), 500)
|
||||
},
|
||||
onError() {
|
||||
toast.error(`Error deleting account`)
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-md mx-auto">
|
||||
<h3 className="text-center">
|
||||
Unfortunately we're only accepting users from the US for now
|
||||
</h3>
|
||||
<div className="mt-4 space-y-4 text-base text-gray-50">
|
||||
<p>We hate doing this, but for now we’re only accepting users from the US. Why?</p>
|
||||
<p>
|
||||
Well besides not being able to automatically connect to your institution, our
|
||||
financial advisors wouldn’t be able to give you relevant localized advice and
|
||||
would likely breach some regulations.
|
||||
</p>
|
||||
<p>
|
||||
That being said, we do plan on expanding Maybe to other countries soon. So we’ll
|
||||
let you know via email once we launch Maybe in {country || 'your country'}.
|
||||
</p>
|
||||
</div>
|
||||
<Link href="https://maybe.co" passHref>
|
||||
<Button as="a" fullWidth className="mt-8">
|
||||
Got it
|
||||
</Button>
|
||||
</Link>
|
||||
<Button
|
||||
variant="warn"
|
||||
fullWidth
|
||||
className="mt-4"
|
||||
disabled={deleteUser.isLoading}
|
||||
onClick={() => {
|
||||
if (
|
||||
// eslint-disable-next-line
|
||||
confirm(
|
||||
'Are you sure you want to delete your account? This cannot be undone.'
|
||||
)
|
||||
) {
|
||||
deleteUser.mutate({})
|
||||
}
|
||||
}}
|
||||
>
|
||||
{deleteUser.isLoading ? 'Deleting account...' : 'Delete my account'}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -29,7 +29,6 @@ import type { StepProps } from './StepProps'
|
|||
import { Switch } from '@headlessui/react'
|
||||
import { BrowserUtil, useUserApi } from '@maybe-finance/client/shared'
|
||||
import type { Household, MaybeGoal } from '@prisma/client'
|
||||
import { CountryWaitlist } from './CountryWaitlist'
|
||||
import { DateUtil, Geo } from '@maybe-finance/shared'
|
||||
|
||||
type FormValues = {
|
||||
|
@ -73,7 +72,7 @@ export function Profile({ title, onNext }: StepProps) {
|
|||
dob: data.dob,
|
||||
household: data.household,
|
||||
country: data.country,
|
||||
state: data.country === 'US' ? data.state : null, // should be NULL if country is not US
|
||||
state: null, // should always be null for now
|
||||
maybeGoals: data.maybeGoals,
|
||||
maybeGoalsDescription: data.maybeGoalsDescription,
|
||||
})
|
||||
|
@ -108,7 +107,6 @@ function ProfileForm({ title, onSubmit, defaultValues }: ProfileViewProps) {
|
|||
})
|
||||
|
||||
const country = watch('country')
|
||||
const [showCountryWaitlist, setShowCountryWaitlist] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
trigger()
|
||||
|
@ -116,9 +114,7 @@ function ProfileForm({ title, onSubmit, defaultValues }: ProfileViewProps) {
|
|||
|
||||
const { errors } = useFormState({ control })
|
||||
|
||||
return showCountryWaitlist ? (
|
||||
<CountryWaitlist country={Geo.countries.find((c) => c.code === country)?.name} />
|
||||
) : (
|
||||
return (
|
||||
<div className="w-full max-w-md mx-auto">
|
||||
<h3 className="text-center">{title}</h3>
|
||||
<p className="mt-4 text-base text-gray-50">
|
||||
|
@ -211,18 +207,12 @@ function ProfileForm({ title, onSubmit, defaultValues }: ProfileViewProps) {
|
|||
|
||||
<Question
|
||||
open={currentQuestion === 'residence'}
|
||||
valid={!errors.country && (!errors.state || country !== 'US')}
|
||||
valid={!errors.country}
|
||||
icon={RiMapPin2Line}
|
||||
label="Where are you based?"
|
||||
onClick={() => setCurrentQuestion('residence')}
|
||||
back={() => setCurrentQuestion('household')}
|
||||
next={() => {
|
||||
if (country === 'US') {
|
||||
setCurrentQuestion('goals')
|
||||
} else {
|
||||
setShowCountryWaitlist(true)
|
||||
}
|
||||
}}
|
||||
next={() => setCurrentQuestion('goals')}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
<Controller
|
||||
|
@ -246,29 +236,6 @@ function ProfileForm({ title, onSubmit, defaultValues }: ProfileViewProps) {
|
|||
</Listbox>
|
||||
)}
|
||||
/>
|
||||
|
||||
{country === 'US' && (
|
||||
<Controller
|
||||
name="state"
|
||||
control={control}
|
||||
rules={{ required: true }}
|
||||
render={({ field }) => (
|
||||
<Listbox {...field}>
|
||||
<Listbox.Button label="State">
|
||||
{Geo.states.find((s) => s.code === field.value)?.name ||
|
||||
'Select'}
|
||||
</Listbox.Button>
|
||||
<Listbox.Options className="max-h-[300px] custom-gray-scroll">
|
||||
{Geo.states.map((state) => (
|
||||
<Listbox.Option key={state.code} value={state.code}>
|
||||
{state.name}
|
||||
</Listbox.Option>
|
||||
))}
|
||||
</Listbox.Options>
|
||||
</Listbox>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<Tooltip
|
||||
placement="bottom-start"
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
import { useSession } from 'next-auth/react'
|
||||
import { Button, Dialog } from '@maybe-finance/design-system'
|
||||
import { useState } from 'react'
|
||||
import axios from 'axios'
|
||||
import toast from 'react-hot-toast'
|
||||
|
||||
export interface FeedbackDialogProps {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
notImplementedNotice?: boolean
|
||||
}
|
||||
|
||||
export function FeedbackDialog({ isOpen, onClose, notImplementedNotice }: FeedbackDialogProps) {
|
||||
const [feedback, setFeedback] = useState('')
|
||||
const { data: session } = useSession()
|
||||
|
||||
return (
|
||||
<Dialog isOpen={isOpen} onClose={onClose}>
|
||||
<Dialog.Title>Send us your feedback!</Dialog.Title>
|
||||
<Dialog.Content>
|
||||
{notImplementedNotice ? (
|
||||
<p className="text-sm text-white mb-6">
|
||||
This feature has not been implemented yet, but is coming soon! Mind helping
|
||||
us out and telling us what you want with this particular feature below?
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-sm text-gray-100 mb-6">
|
||||
Maybe is built in public and relies heavily on user feedback. We'd love to
|
||||
hear what you think could be better (please be constructive, we're still in
|
||||
the early days!{' '}
|
||||
<span role="img" aria-label="happy emoji">
|
||||
😄
|
||||
</span>
|
||||
)
|
||||
</p>
|
||||
)}
|
||||
<form
|
||||
onSubmit={async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
try {
|
||||
await axios
|
||||
.create({ transformRequest: [(data) => JSON.stringify(data)] })
|
||||
.post(
|
||||
process.env.NEXT_PUBLIC_ZAPIER_FEEDBACK_HOOK_URL ||
|
||||
'REPLACE_THIS',
|
||||
{
|
||||
comment: `**From user:** ${session?.user?.email}\n\n${feedback}`,
|
||||
page: `**Main app feedback**: ${window.location.href}`,
|
||||
}
|
||||
)
|
||||
|
||||
toast.success('Your feedback was submitted!')
|
||||
} catch (e) {
|
||||
toast.error('Feedback not submitted')
|
||||
}
|
||||
|
||||
onClose()
|
||||
}}
|
||||
>
|
||||
<textarea
|
||||
value={feedback}
|
||||
onChange={(e) => setFeedback(e.target.value)}
|
||||
className="w-full rounded bg-gray-500 text-base border-0 focus:ring focus:ring-opacity-60 focus:ring-cyan"
|
||||
rows={6}
|
||||
></textarea>
|
||||
<Button className="mt-4" type="submit" disabled={feedback.length < 10}>
|
||||
Submit
|
||||
</Button>
|
||||
</form>
|
||||
</Dialog.Content>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
|
@ -1,2 +1 @@
|
|||
export * from './FeedbackDialog'
|
||||
export * from './NonUSDDialog'
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import { Button } from '@maybe-finance/design-system'
|
||||
import { useState } from 'react'
|
||||
import { FeedbackDialog } from '../dialogs'
|
||||
|
||||
export function FeedbackButton() {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
return (
|
||||
<div className="mt-6 text-center">
|
||||
<Button onClick={() => setIsOpen(true)}>Send us your feedback</Button>
|
||||
<FeedbackDialog isOpen={isOpen} onClose={() => setIsOpen(false)} />
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
export * from './FeedbackButton'
|
||||
export * from './TrendBadge'
|
||||
export * from './Toaster'
|
||||
export * from './BoxIcon'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue