mirror of
https://github.com/aljazceru/landscape-template.git
synced 2026-01-24 16:54:23 +01:00
Merge branch 'dev' into feature/new-project-page
This commit is contained in:
16
README.md
16
README.md
@@ -32,9 +32,19 @@ We are using serverless functions to serve our GraphQl endpoint to the client ap
|
||||
|
||||
## Running locally
|
||||
|
||||
First, you need to have a Postegre Database to store the data, then you need to put the connection string in an .env file in your project root directory.
|
||||
The connection string will be of the format:
|
||||
postgresql://username:password@server/database_name
|
||||
To run the project locally with your own local DB, you will need to first put a few env variables in an env file that should be created in /envs/server directory, named `local.env`
|
||||
|
||||
The required variables that needs to be put there are:
|
||||
|
||||
```
|
||||
NODE_ENV = "development"
|
||||
DATABASE_PROXY_URL = "YOUR DB CONNECTION STRING"
|
||||
JWT_SECRET = "SOME RANDOM JWT SECRET"
|
||||
LNURL_AUTH_HOST = "http://localhost:8888/dev/login"
|
||||
CLOUDFLARE_IMAGE_ACCOUNT_ID = "FOR UPLOADING IMAGES"
|
||||
CLOUDFLARE_IMAGE_API_KEY = "FOR UPLOADING IMAGES"
|
||||
CLOUDFLARE_IMAGE_ACCOUNT_HASH = "FOR UPLOADING IMAGES"
|
||||
```
|
||||
|
||||
Then you need to run the migrations against your database.
|
||||
use the command:
|
||||
|
||||
@@ -182,7 +182,7 @@ export default function LoginPage() {
|
||||
color='gray'
|
||||
onClick={copyToClipboard}
|
||||
>{copied ? "Copied" : "Copy"} <FiCopy /></Button>
|
||||
<a href={`https://makers.bolt.fun/blog/post/story/99/sign-in-with-lightning`} target='_blank' rel="noreferrer"
|
||||
<a href={`https://makers.bolt.fun/story/sign-in-with-lightning--99`} target='_blank' rel="noreferrer"
|
||||
className='md:col-span-2 block text-body4 text-center text-gray-900 border border-gray-200 rounded-10 px-16 py-12 active:scale-90 transition-transform'
|
||||
>What is a lightning wallet?</a>
|
||||
</div>
|
||||
|
||||
@@ -91,7 +91,7 @@ export default function FeedPage() {
|
||||
<div className="pb-16 md:overflow-y-scroll sticky-side-element">
|
||||
<h1 className="text-h2 font-bolder mb-24">Discover</h1>
|
||||
<Button
|
||||
href={PAGES_ROUTES.blog.writeStory}
|
||||
href={createRoute({ type: "write-story" })}
|
||||
color='primary'
|
||||
fullWidth
|
||||
>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { NotificationsService } from "src/services/notifications.service";
|
||||
import { useAppDispatch } from "src/utils/hooks";
|
||||
import { useReduxEffect } from "src/utils/hooks/useReduxEffect";
|
||||
import { openModal } from "src/redux/features/modals.slice";
|
||||
import { createRoute } from "src/utils/routing";
|
||||
|
||||
|
||||
const CONFIRM_DELETE_STORY = createAction<{ confirmed?: boolean }>('DELETE_STORY_CONFIRMED')({})
|
||||
@@ -31,7 +32,7 @@ export const useUpdateStory = (story: Story) => {
|
||||
cover_image: story.cover_image ? { id: null, name: null, url: story.cover_image } : null,
|
||||
}))
|
||||
|
||||
navigate("/blog/create-post?type=story")
|
||||
navigate(createRoute({ type: "write-story" }))
|
||||
};
|
||||
|
||||
const onConfirmDelete = useCallback(({ payload: { confirmed } }: typeof CONFIRM_DELETE_STORY) => {
|
||||
|
||||
@@ -12,12 +12,13 @@ import { BsLightningChargeFill } from "react-icons/bs";
|
||||
import InfoCard from "src/Components/InfoCard/InfoCard";
|
||||
import TextInput from "src/Components/Inputs/TextInput/TextInput";
|
||||
import TextareaInput from "src/Components/Inputs/TextareaInput/TextareaInput";
|
||||
import { registerDebounceValidation } from "src/utils/validation";
|
||||
|
||||
interface Props { }
|
||||
|
||||
export default function ProjectDetailsTab(props: Props) {
|
||||
|
||||
const { register, formState: { errors, dirtyFields }, control, getValues } = useFormContext<IListProjectForm>();
|
||||
const { register, formState: { errors, dirtyFields }, control, getValues, trigger } = useFormContext<IListProjectForm>();
|
||||
|
||||
const isUpdating = !!getValues('id');
|
||||
|
||||
@@ -117,7 +118,7 @@ export default function ProjectDetailsTab(props: Props) {
|
||||
placeholder='my_project_name'
|
||||
inputClass="pl-8"
|
||||
renderBefore={() => <span className="flex flex-col justify-center pl-16 shrink-0">#</span>}
|
||||
{...register("hashtag")}
|
||||
{...registerDebounceValidation("hashtag", 1000, trigger, register)}
|
||||
/>
|
||||
{errors.hashtag && <p className="input-error">
|
||||
{errors.hashtag.message}
|
||||
|
||||
@@ -62,10 +62,15 @@ export default function MakerCard({ maker, isMe }: Props) {
|
||||
<Card>
|
||||
<div className="flex flex-wrap gap-24 items-start">
|
||||
<div className="shrink-0 w-64 md:w-80">
|
||||
<Avatar src={maker.user.avatar} width={'100%'}></Avatar>
|
||||
<Link to={createRoute({ type: "profile", id: maker.user.id, username: maker.user.name })}>
|
||||
<Avatar src={maker.user.avatar} width={'100%'}></Avatar>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 flex-1 overflow-hidden">
|
||||
<p className="text-body2 text-gray-900 font-bold overflow-hidden text-ellipsis">{maker.user.name}</p>
|
||||
|
||||
<Link to={createRoute({ type: "profile", id: maker.user.id, username: maker.user.name })}>
|
||||
<p className="text-body2 text-gray-900 font-bold overflow-hidden text-ellipsis">{maker.user.name}</p>
|
||||
</Link>
|
||||
{maker.user.jobTitle ? <p className="text-body4 text-gray-600 font-medium">{maker.user.jobTitle}</p>
|
||||
:
|
||||
<p className="text-body4 text-gray-400 font-medium">No job title</p>}
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function MakersPage() {
|
||||
{query.loading ?
|
||||
<MakerCardSkeleton />
|
||||
:
|
||||
query.data?.me ?
|
||||
(query.data?.me && !!query.data.tournamentParticipationInfo) ?
|
||||
<MakerCard isMe maker={{ user: query.data.me as User, hacking_status: query.data.tournamentParticipationInfo?.hacking_status! }} />
|
||||
: null
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ export default function LinkingAccountModal({ onClose, direction, tournamentId,
|
||||
color='gray'
|
||||
onClick={copyToClipboard}
|
||||
>{copied ? "Copied" : "Copy"} <FiCopy /></Button>
|
||||
<a href={`https://makers.bolt.fun/blog/post/story/99/sign-in-with-lightning`} target='_blank' rel="noreferrer"
|
||||
<a href={`https://makers.bolt.fun/story/sign-in-with-lightning--99`} target='_blank' rel="noreferrer"
|
||||
className='col-span-2 block text-body4 text-center text-gray-900 border border-gray-200 rounded-10 px-16 py-12 active:scale-90 transition-transform'
|
||||
>What is a lightning wallet?</a>
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,7 @@ type RouteOptions =
|
||||
username?: string,
|
||||
}
|
||||
| {
|
||||
type: "edit-story",
|
||||
type: "write-story",
|
||||
id?: number,
|
||||
}
|
||||
| {
|
||||
@@ -66,6 +66,10 @@ export function createRoute(options: RouteOptions) {
|
||||
+ (!onlyId ? "-" : "")
|
||||
+ `${options.id}`
|
||||
}
|
||||
|
||||
if (options.type === 'write-story')
|
||||
return "/story/write?type=story"
|
||||
|
||||
if ((options.type === "post" && options.postType.toLowerCase() === 'bounty')
|
||||
|| options.type === "bounty")
|
||||
return `/blog/post/bounty/${options.id}`
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import * as yup from "yup";
|
||||
import { FieldPath, RegisterOptions, UseFormRegister, UseFormRegisterReturn, UseFormTrigger } from 'react-hook-form'
|
||||
import debounce from "lodash.debounce";
|
||||
|
||||
export const imageSchema = yup.object().shape({
|
||||
id: yup.string().nullable(true),
|
||||
@@ -10,3 +12,25 @@ export const tagSchema = yup.object().shape({
|
||||
title: yup.string().trim().min(2).required(),
|
||||
});
|
||||
|
||||
|
||||
|
||||
export const registerDebounceValidation = <TFieldValues>(
|
||||
name: FieldPath<TFieldValues>,
|
||||
delay: number,
|
||||
trigger: UseFormTrigger<TFieldValues>,
|
||||
register: UseFormRegister<TFieldValues>,
|
||||
options?: RegisterOptions<TFieldValues, FieldPath<TFieldValues>>
|
||||
) => {
|
||||
const useFormRegisterReturn: UseFormRegisterReturn = register(name, options)
|
||||
const { onChange } = useFormRegisterReturn
|
||||
const debouncedValidate = debounce(() => {
|
||||
trigger(name)
|
||||
}, delay)
|
||||
return {
|
||||
...useFormRegisterReturn,
|
||||
onChange: (e: any) => {
|
||||
onChange(e)
|
||||
debouncedValidate()
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user