diff --git a/web/components/create-fold-button.tsx b/web/components/create-fold-button.tsx new file mode 100644 index 00000000..52e773d6 --- /dev/null +++ b/web/components/create-fold-button.tsx @@ -0,0 +1,137 @@ +import clsx from 'clsx' +import { useRouter } from 'next/router' +import { useState } from 'react' +import { parseWordsAsTags } from '../../common/util/parse' +import { createFold } from '../lib/firebase/api-call' +import { foldPath } from '../lib/firebase/folds' +import { toCamelCase } from '../lib/util/format' +import { ConfirmationButton } from './confirmation-button' +import { Col } from './layout/col' +import { Spacer } from './layout/spacer' +import { TagsList } from './tags-list' +import { Title } from './title' + +export function CreateFoldButton() { + const [name, setName] = useState('') + const [about, setAbout] = useState('') + const [otherTags, setOtherTags] = useState('') + const [isSubmitting, setIsSubmitting] = useState(false) + + const router = useRouter() + + const tags = parseWordsAsTags(toCamelCase(name) + ' ' + otherTags) + + const updateName = (newName: string) => { + setName(newName) + } + + const onSubmit = async () => { + setIsSubmitting(true) + + const result = await createFold({ + name, + tags, + about, + }).then((r) => r.data || {}) + + if (result.fold) { + await router.push(foldPath(result.fold)).catch((e) => { + console.log(e) + setIsSubmitting(false) + }) + } else { + console.log(result.status, result.message) + setIsSubmitting(false) + } + } + + return ( + + + + <Col className="text-gray-500 gap-1"> + <div>A fold is a sub-community of markets organized on a topic.</div> + <div>Markets are included if they match one or more tags.</div> + </Col> + + <Spacer h={4} /> + + <div> + <div className="form-control w-full"> + <label className="label"> + <span className="mb-1">Fold name</span> + </label> + + <input + placeholder="Your fold name" + className="input input-bordered resize-none" + disabled={isSubmitting} + value={name} + onChange={(e) => updateName(e.target.value || '')} + /> + </div> + + <Spacer h={4} /> + + <div className="form-control w-full"> + <label className="label"> + <span className="mb-1">About</span> + </label> + + <input + placeholder="Short description (140 characters max)" + className="input input-bordered resize-none" + disabled={isSubmitting} + value={about} + maxLength={140} + onChange={(e) => setAbout(e.target.value || '')} + /> + </div> + + <Spacer h={4} /> + + <label className="label"> + <span className="mb-1">Primary tag</span> + </label> + <TagsList noLink tags={[`#${toCamelCase(name)}`]} /> + + <Spacer h={4} /> + + <div className="form-control w-full"> + <label className="label"> + <span className="mb-1">Additional tags</span> + </label> + + <input + placeholder="Politics, Economics, Rationality (Optional)" + className="input input-bordered resize-none" + disabled={isSubmitting} + value={otherTags} + onChange={(e) => setOtherTags(e.target.value || '')} + /> + </div> + + <Spacer h={4} /> + + <TagsList + tags={parseWordsAsTags(otherTags).map((tag) => `#${tag}`)} + noLink + /> + </div> + </ConfirmationButton> + ) +} diff --git a/web/lib/firebase/api-call.ts b/web/lib/firebase/api-call.ts index a0fc7de8..d92122e0 100644 --- a/web/lib/firebase/api-call.ts +++ b/web/lib/firebase/api-call.ts @@ -2,6 +2,7 @@ import { getFunctions, httpsCallable } from 'firebase/functions' import { Fold } from '../../../common/fold' import { User } from '../../../common/user' import { randomString } from '../../../common/util/random' +import './init' const functions = getFunctions() diff --git a/web/pages/folds.tsx b/web/pages/folds.tsx index d6be19e9..3a1316ac 100644 --- a/web/pages/folds.tsx +++ b/web/pages/folds.tsx @@ -1,24 +1,17 @@ -import clsx from 'clsx' import _ from 'lodash' -import { useRouter } from 'next/router' import { useEffect, useState } from 'react' import { Fold } from '../../common/fold' -import { parseWordsAsTags } from '../../common/util/parse' -import { ConfirmationButton } from '../components/confirmation-button' +import { CreateFoldButton } from '../components/create-fold-button' import { Col } from '../components/layout/col' import { Row } from '../components/layout/row' -import { Spacer } from '../components/layout/spacer' import { Page } from '../components/page' import { SiteLink } from '../components/site-link' -import { TagsList } from '../components/tags-list' import { Title } from '../components/title' import { UserLink } from '../components/user-page' import { useFolds } from '../hooks/use-fold' import { useUser } from '../hooks/use-user' -import { createFold } from '../lib/firebase/api-call' import { foldPath, listAllFolds } from '../lib/firebase/folds' import { getUser, User } from '../lib/firebase/users' -import { toCamelCase } from '../lib/util/format' export async function getStaticProps() { const folds = await listAllFolds().catch((_) => []) @@ -79,20 +72,24 @@ export default function Folds(props: { <Col className="gap-4"> {folds.map((fold) => ( - <Row key={fold.id} className="items-center gap-2"> - <SiteLink href={foldPath(fold)}>{fold.name}</SiteLink> - <div /> - <div className="text-sm text-gray-500">12 followers</div> - <div className="text-gray-500">•</div> - <Row> - <div className="text-sm text-gray-500 mr-1">Curated by</div> - <UserLink - className="text-sm text-neutral" - name={curatorsDict[fold.curatorId]?.name ?? ''} - username={curatorsDict[fold.curatorId]?.username ?? ''} - /> + <Col key={fold.id} className="gap-2"> + <Row className="items-center flex-wrap gap-2"> + <SiteLink href={foldPath(fold)}>{fold.name}</SiteLink> + <div /> + <div className="text-sm text-gray-500">12 followers</div> + <div className="text-gray-500">•</div> + <Row> + <div className="text-sm text-gray-500 mr-1">Curated by</div> + <UserLink + className="text-sm text-neutral" + name={curatorsDict[fold.curatorId]?.name ?? ''} + username={curatorsDict[fold.curatorId]?.username ?? ''} + /> + </Row> </Row> - </Row> + <div className="text-gray-500 text-sm">{fold.about}</div> + <div /> + </Col> ))} </Col> </Col> @@ -100,128 +97,3 @@ export default function Folds(props: { </Page> ) } - -function CreateFoldButton() { - const [name, setName] = useState('') - const [about, setAbout] = useState('') - const [otherTags, setOtherTags] = useState('') - const [isSubmitting, setIsSubmitting] = useState(false) - - const router = useRouter() - - const tags = parseWordsAsTags(toCamelCase(name) + ' ' + otherTags) - - const updateName = (newName: string) => { - setName(newName) - } - - const onSubmit = async () => { - setIsSubmitting(true) - - const result = await createFold({ - name, - tags, - about, - }).then((r) => r.data || {}) - - if (result.fold) { - await router.push(foldPath(result.fold)).catch((e) => { - console.log(e) - setIsSubmitting(false) - }) - } else { - console.log(result.status, result.message) - setIsSubmitting(false) - } - } - - return ( - <ConfirmationButton - id="create-fold" - openModelBtn={{ - label: 'Create a fold', - className: clsx( - isSubmitting ? 'loading btn-disabled' : 'btn-primary', - 'btn-sm' - ), - }} - submitBtn={{ - label: 'Create', - className: clsx(name && about ? 'btn-primary' : 'btn-disabled'), - }} - onSubmit={onSubmit} - > - <Title className="!mt-0" text="Create a fold" /> - - <Col className="text-gray-500 gap-1"> - <div>A fold is a sub-community of markets organized on a topic.</div> - <div>Markets are included if they match one or more tags.</div> - </Col> - - <Spacer h={4} /> - - <div> - <div className="form-control w-full"> - <label className="label"> - <span className="mb-1">Fold name</span> - </label> - - <input - placeholder="Your fold name" - className="input input-bordered resize-none" - disabled={isSubmitting} - value={name} - onChange={(e) => updateName(e.target.value || '')} - /> - </div> - - <Spacer h={4} /> - - <div className="form-control w-full"> - <label className="label"> - <span className="mb-1">About</span> - </label> - - <input - placeholder="Short description (140 characters max)" - className="input input-bordered resize-none" - disabled={isSubmitting} - value={about} - maxLength={140} - onChange={(e) => setAbout(e.target.value || '')} - /> - </div> - - <Spacer h={4} /> - - <label className="label"> - <span className="mb-1">Primary tag</span> - </label> - <TagsList noLink tags={[`#${toCamelCase(name)}`]} /> - - <Spacer h={4} /> - - <div className="form-control w-full"> - <label className="label"> - <span className="mb-1">Additional tags</span> - </label> - - <input - placeholder="Politics, Economics, Rationality (Optional)" - className="input input-bordered resize-none" - disabled={isSubmitting} - value={otherTags} - onChange={(e) => setOtherTags(e.target.value || '')} - /> - </div> - - <Spacer h={4} /> - - <TagsList - tags={parseWordsAsTags(otherTags).map((tag) => `#${tag}`)} - noLink - /> - </div> - </ConfirmationButton> - ) -}