diff --git a/src/components/users/ImportFromMtnProj.tsx b/src/components/users/ImportFromMtnProj.tsx
index 99a83c988..9f0141330 100644
--- a/src/components/users/ImportFromMtnProj.tsx
+++ b/src/components/users/ImportFromMtnProj.tsx
@@ -1,7 +1,7 @@
-import { Fragment, useEffect, useState } from 'react'
+import { useState } from 'react'
import { useRouter } from 'next/router'
-import { Transition } from '@headlessui/react'
-import { FolderArrowDownIcon, XMarkIcon } from '@heroicons/react/24/outline'
+import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'
+import { FolderArrowDownIcon } from '@heroicons/react/24/outline'
import { useMutation } from '@apollo/client'
import { signIn, useSession } from 'next-auth/react'
import { toast } from 'react-toastify'
@@ -10,9 +10,10 @@ import clx from 'classnames'
import { graphqlClient } from '../../js/graphql/Client'
import { MUTATION_IMPORT_TICKS } from '../../js/graphql/gql/fragments'
import { INPUT_DEFAULT_CSS } from '../ui/form/TextArea'
+import Spinner from '../ui/Spinner'
+import { LeanAlert } from '../ui/micro/AlertDialogue'
interface Props {
- isButton: boolean
username: string
}
// regex pattern to validate mountain project input
@@ -20,13 +21,11 @@ const pattern = /^https:\/\/www.mountainproject.com\/user\/\d{9}\/[a-zA-Z-]*/
/**
*
- * @prop isButton -- a true or false value
+ * @prop username -- the openbeta username of the user
*
- * if the isButton prop is true, the component will be rendered as a button
- * if the isButton prop is false, the component will be rendered as a modal
* @returns JSX element
*/
-export function ImportFromMtnProj ({ isButton, username }: Props): JSX.Element {
+export function ImportFromMtnProj ({ username }: Props): JSX.Element {
const router = useRouter()
const [mpUID, setMPUID] = useState('')
const session = useSession()
@@ -40,19 +39,35 @@ export function ImportFromMtnProj ({ isButton, username }: Props): JSX.Element {
errorPolicy: 'none'
})
- // this function updates the users metadata
- async function dontShowAgain (): Promise {
- setLoading(true)
- const res = await fetch('/api/user/ticks', {
- method: 'PUT',
- body: ''
- })
- if (res.status === 200) {
- setShow(false)
- } else {
- setErrors(['Sorry, something went wrong. Please try again later'])
+ async function fetchMPData (url: string, method: 'GET' | 'POST' | 'PUT' = 'GET', body?: string): Promise {
+ try {
+ const headers = {
+ 'Content-Type': 'application/json'
+ }
+ const config: RequestInit = {
+ method,
+ headers
+ }
+
+ if (body !== null && body !== undefined && body !== '') {
+ config.body = JSON.stringify(body)
+ }
+
+ const response = await fetch(url, config)
+
+ if (!response.ok) {
+ const errorData = await response.json()
+ throw new Error(errorData.statusText)
+ }
+
+ return await response.json()
+ } catch (error) {
+ if (error instanceof Error) {
+ console.error('Fetch error:', error.message)
+ throw error
+ }
+ throw new Error('An unexpected error occurred')
}
- setLoading(false)
}
// this function is for when the component is rendered as a button and sends the user straight to the input form
@@ -67,26 +82,41 @@ export function ImportFromMtnProj ({ isButton, username }: Props): JSX.Element {
async function getTicks (): Promise {
// get the ticks and add it to the database
+ setErrors([])
if (pattern.test(mpUID)) {
setLoading(true)
- const res = await fetch('/api/user/ticks', {
- method: 'POST',
- body: JSON.stringify(mpUID)
- })
- if (res.status === 200) {
- setShow(false)
- const { ticks } = await res.json()
- await addTicks({
- variables: {
- input: ticks
- }
- })
-
- const ticksCount: number = ticks?.length ?? 0
- toast.info(`${ticksCount} ticks have been imported!`)
- await router.replace(`/u2/${username}`)
- } else {
- setErrors(['Sorry, something went wrong. Please try again later'])
+
+ try {
+ const response = await fetchMPData('/api/user/ticks', 'POST', JSON.stringify(mpUID))
+
+ if (response.ticks[0] !== undefined) {
+ await addTicks({
+ variables: {
+ input: response.ticks
+ }
+ })
+ // Add a delay before rerouting to the new page
+ const ticksCount: number = response.ticks?.length ?? 0
+ toast.info(
+ <>
+ {ticksCount} ticks have been imported! 🎉
+ Redirecting in a few seconds...`
+ >
+ )
+
+ setTimeout(() => {
+ void router.replace(`/u2/${username}`)
+ }, 2000)
+ setShow(false)
+ } else {
+ setErrors(['Sorry, no ticks were found for that user. Please check your Mountain Project ID and try again.'])
+ toast.error('Sorry, no ticks were found for that user. Please check your Mountain Project ID and try again.')
+ }
+ } catch (error) {
+ toast.error('Sorry, something went wrong. Please check your network and try again.')
+ setErrors(['Sorry, something went wrong. Please check your network and try again.'])
+ } finally {
+ setLoading(false)
}
} else {
// handle errors
@@ -95,120 +125,69 @@ export function ImportFromMtnProj ({ isButton, username }: Props): JSX.Element {
setLoading(false)
}
- useEffect(() => {
- // if we aren't rendering this component as a button
- // and the user is authenticated we want to show the import your ticks modal
- // then we check to see if they have a ticks imported flag set
- // if it is, set show to the opposite of whatever it is
- // otherwise don't show the modal
- if (!isButton) {
- fetch('/api/user/profile')
- .then(async res => await res.json())
- .then((profile) => {
- if (profile?.ticksImported !== null) {
- setShow(profile.ticksImported !== true)
- } else if (session.status === 'authenticated') {
- setShow(true)
- } else {
- setShow(false)
- }
- }).catch(console.error)
- }
- }, [session])
-
- // if the isButton prop is passed to this component as true, the component will be rendered as a button, otherwise it will be a modal
return (
<>
- {isButton && }
-