mirror of
https://github.com/aljazceru/landscape-template.git
synced 2025-12-27 11:14:33 +01:00
update: remove edit state from the AboutCard in profile page
This commit is contained in:
@@ -3,8 +3,7 @@ import { User } from "src/graphql"
|
||||
import { trimText, withHttp } from "src/utils/helperFunctions"
|
||||
import { FiGithub, FiGlobe, FiLinkedin, FiTwitter } from 'react-icons/fi'
|
||||
import Button from "src/Components/Button/Button";
|
||||
import { useToggle } from "@react-hookz/web";
|
||||
import UpdateAboutForm from "./UpdateAboutForm";
|
||||
import { PAGES_ROUTES } from "src/utils/routing";
|
||||
|
||||
interface Props {
|
||||
isOwner?: boolean;
|
||||
@@ -52,7 +51,6 @@ export default function AboutCard({ user, isOwner }: Props) {
|
||||
}
|
||||
];
|
||||
|
||||
const [editMode, toggleEditMode] = useToggle(false);
|
||||
|
||||
return (
|
||||
<div className="rounded-16 bg-white border-2 border-gray-200">
|
||||
@@ -62,51 +60,44 @@ export default function AboutCard({ user, isOwner }: Props) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-64 flex justify-end items-center px-24">
|
||||
{(isOwner && !editMode) && <Button size="sm" color="gray" onClick={() => toggleEditMode(true)}>Edit Profile</Button>}
|
||||
{(isOwner) && <Button size="sm" color="gray" href='/edit-profile'>Edit Profile</Button>}
|
||||
</div>
|
||||
<div className="p-24 pt-0">
|
||||
{editMode === true ?
|
||||
<div className="flex flex-col gap-16">
|
||||
<h1 className="text-h2 font-bolder">
|
||||
{trimText(user.name, 20)}
|
||||
</h1>
|
||||
|
||||
<UpdateAboutForm data={user} onClose={toggleEditMode} />
|
||||
{links.some(link => link.hasValue) && <div className="flex flex-wrap gap-16">
|
||||
{links.filter(link => link.hasValue || isOwner).map((link, idx) => link.hasValue ?
|
||||
<a
|
||||
key={idx}
|
||||
href={link.url!}
|
||||
className="text-body4 text-primary-700 font-medium"
|
||||
target='_blank'
|
||||
rel="noreferrer">
|
||||
<link.icon className="scale-125 mr-8" /> <span className="align-middle">{link.text}</span>
|
||||
</a> :
|
||||
<p
|
||||
key={idx}
|
||||
className="text-body4 text-primary-700 font-medium"
|
||||
>
|
||||
<link.icon className="scale-125 mr-8" /> <span className="align-middle">---</span>
|
||||
</p>)}
|
||||
</div>}
|
||||
|
||||
:
|
||||
{(user.jobTitle || isOwner) && <p className="text-body4 font-medium">
|
||||
{user.jobTitle ? user.jobTitle : "No job title added"}
|
||||
</p>}
|
||||
|
||||
<div className="flex flex-col gap-16">
|
||||
<h1 className="text-h2 font-bolder">
|
||||
{trimText(user.name, 20)}
|
||||
</h1>
|
||||
{(user.lightning_address || isOwner) && <p className="text-body5 font-medium">
|
||||
{user.lightning_address ? `⚡${user.lightning_address}` : "⚡ No lightning address"}
|
||||
</p>}
|
||||
|
||||
{links.some(link => link.hasValue) && <div className="flex flex-wrap gap-16">
|
||||
{links.filter(link => link.hasValue || isOwner).map((link, idx) => link.hasValue ?
|
||||
<a
|
||||
key={idx}
|
||||
href={link.url!}
|
||||
className="text-body4 text-primary-700 font-medium"
|
||||
target='_blank'
|
||||
rel="noreferrer">
|
||||
<link.icon className="scale-125 mr-8" /> <span className="align-middle">{link.text}</span>
|
||||
</a> :
|
||||
<p
|
||||
key={idx}
|
||||
className="text-body4 text-primary-700 font-medium"
|
||||
>
|
||||
<link.icon className="scale-125 mr-8" /> <span className="align-middle">---</span>
|
||||
</p>)}
|
||||
</div>}
|
||||
|
||||
{(user.jobTitle || isOwner) && <p className="text-body4 font-medium">
|
||||
{user.jobTitle ? user.jobTitle : "No job title added"}
|
||||
</p>}
|
||||
|
||||
{(user.lightning_address || isOwner) && <p className="text-body5 font-medium">
|
||||
{user.lightning_address ? `⚡${user.lightning_address}` : "⚡ No lightning address"}
|
||||
</p>}
|
||||
|
||||
{(user.bio || isOwner) && <p className="text-body5 font-medium">
|
||||
{user.bio ? user.bio : "No bio added"}
|
||||
</p>}
|
||||
</div>
|
||||
}
|
||||
{(user.bio || isOwner) && <p className="text-body5 font-medium">
|
||||
{user.bio ? user.bio : "No bio added"}
|
||||
</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
import { ComponentProps } from "react"
|
||||
import { SubmitHandler, useForm } from "react-hook-form"
|
||||
import Button from "src/Components/Button/Button";
|
||||
import { useUpdateProfileAboutMutation } from "src/graphql";
|
||||
import { NotificationsService } from "src/services/notifications.service";
|
||||
import AboutCard from "./AboutCard"
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
|
||||
interface Props {
|
||||
data: ComponentProps<typeof AboutCard>['user'],
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
type IFormInputs = Props['data'];
|
||||
|
||||
const schema: yup.SchemaOf<IFormInputs> = yup.object({
|
||||
name: yup.string().trim().required().min(2),
|
||||
avatar: yup.string().url().required(),
|
||||
bio: yup.string().ensure(),
|
||||
email: yup.string().email().ensure(),
|
||||
github: yup.string().ensure(),
|
||||
jobTitle: yup.string().ensure(),
|
||||
lightning_address: yup
|
||||
.string()
|
||||
.test({
|
||||
name: "is valid lightning_address",
|
||||
test: async value => {
|
||||
try {
|
||||
if (value) {
|
||||
const [name, domain] = value.split("@");
|
||||
const lnurl = `https://${domain}/.well-known/lnurlp/${name}`;
|
||||
const res = await fetch(lnurl);
|
||||
if (res.status === 200) return true;
|
||||
}
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
})
|
||||
.ensure()
|
||||
.label("lightning address"),
|
||||
linkedin: yup.string().ensure(),
|
||||
location: yup.string().ensure(),
|
||||
twitter: yup.string().ensure(),
|
||||
website: yup.string().url().ensure(),
|
||||
|
||||
}).required();
|
||||
|
||||
export default function UpdateAboutForm({ data, onClose }: Props) {
|
||||
|
||||
const { register, formState: { errors }, handleSubmit } = useForm<IFormInputs>({
|
||||
defaultValues: data,
|
||||
resolver: yupResolver(schema),
|
||||
mode: 'onBlur',
|
||||
});
|
||||
|
||||
const [mutate, mutationStatus] = useUpdateProfileAboutMutation({
|
||||
onCompleted: () => {
|
||||
onClose?.()
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
const onSubmit: SubmitHandler<IFormInputs> = data => {
|
||||
mutate({
|
||||
variables: {
|
||||
data: {
|
||||
name: data.name,
|
||||
avatar: data.avatar,
|
||||
jobTitle: data.jobTitle,
|
||||
bio: data.bio,
|
||||
email: data.email,
|
||||
github: data.github,
|
||||
linkedin: data.linkedin,
|
||||
lightning_address: data.lightning_address,
|
||||
location: data.location,
|
||||
twitter: data.twitter,
|
||||
website: data.website,
|
||||
}
|
||||
}
|
||||
}).catch(() => {
|
||||
NotificationsService.error('A network error happened');
|
||||
mutationStatus.reset()
|
||||
})
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<p className="text-body5 mt-16 font-medium">
|
||||
Name
|
||||
</p>
|
||||
<div className="input-wrapper mt-8 relative">
|
||||
<input
|
||||
autoFocus
|
||||
type='text'
|
||||
className="input-text"
|
||||
placeholder='John Doe'
|
||||
{...register("name")}
|
||||
/>
|
||||
</div>
|
||||
{errors.name && <p className="input-error">
|
||||
{errors.name.message}
|
||||
</p>}
|
||||
<p className="text-body5 mt-16 font-medium">
|
||||
Avatar
|
||||
</p>
|
||||
<div className="input-wrapper mt-8 relative">
|
||||
<input
|
||||
|
||||
type='text'
|
||||
className="input-text"
|
||||
placeholder='https://images.com/my-avatar.jpg'
|
||||
{...register("avatar")}
|
||||
/>
|
||||
</div>
|
||||
{errors.avatar && <p className="input-error">
|
||||
{errors.avatar.message}
|
||||
</p>}
|
||||
<p className="text-body5 mt-16 font-medium">
|
||||
Bio
|
||||
</p>
|
||||
<div className="input-wrapper mt-8 relative">
|
||||
<textarea
|
||||
|
||||
rows={3}
|
||||
className="input-text !p-20"
|
||||
placeholder='Tell others a little bit about yourself'
|
||||
{...register("bio")}
|
||||
/>
|
||||
</div>
|
||||
{errors.bio && <p className="input-error">
|
||||
{errors.bio.message}
|
||||
</p>}
|
||||
<p className="text-body5 mt-16 font-medium">
|
||||
Job Title
|
||||
</p>
|
||||
<div className="input-wrapper mt-8 relative">
|
||||
<input
|
||||
|
||||
type='text'
|
||||
className="input-text"
|
||||
placeholder="Back-end Developer"
|
||||
{...register("jobTitle")}
|
||||
/>
|
||||
</div>
|
||||
{errors.jobTitle && <p className="input-error">
|
||||
{errors.jobTitle.message}
|
||||
</p>}
|
||||
<p className="text-body5 mt-16 font-medium">
|
||||
Location
|
||||
</p>
|
||||
<div className="input-wrapper mt-8 relative">
|
||||
<input
|
||||
|
||||
type='text'
|
||||
className="input-text"
|
||||
placeholder="UK, London"
|
||||
{...register("location")}
|
||||
/>
|
||||
</div>
|
||||
{errors.location && <p className="input-error">
|
||||
{errors.location.message}
|
||||
</p>}
|
||||
<p className="text-body5 mt-16 font-medium">
|
||||
Website
|
||||
</p>
|
||||
<div className="input-wrapper mt-8 relative">
|
||||
<input
|
||||
|
||||
type='text'
|
||||
className="input-text"
|
||||
placeholder="www.website.io"
|
||||
{...register("website")}
|
||||
/>
|
||||
</div>
|
||||
{errors.website && <p className="input-error">
|
||||
{errors.website.message}
|
||||
</p>}
|
||||
<p className="text-body5 mt-16 font-medium">
|
||||
Twitter
|
||||
</p>
|
||||
<div className="input-wrapper mt-8 relative">
|
||||
<input
|
||||
|
||||
type='text'
|
||||
className="input-text"
|
||||
placeholder="@johndoe"
|
||||
{...register("twitter")}
|
||||
/>
|
||||
</div>
|
||||
{errors.twitter && <p className="input-error">
|
||||
{errors.twitter.message}
|
||||
</p>}
|
||||
<p className="text-body5 mt-16 font-medium">
|
||||
Github
|
||||
</p>
|
||||
<div className="input-wrapper mt-8 relative">
|
||||
<input
|
||||
|
||||
type='text'
|
||||
className="input-text"
|
||||
placeholder="johndoe"
|
||||
{...register("github")}
|
||||
/>
|
||||
</div>
|
||||
{errors.github && <p className="input-error">
|
||||
{errors.github.message}
|
||||
</p>}
|
||||
<p className="text-body5 mt-16 font-medium">
|
||||
Linkedin
|
||||
</p>
|
||||
<div className="input-wrapper mt-8 relative">
|
||||
<input
|
||||
|
||||
type='text'
|
||||
className="input-text"
|
||||
placeholder="www.linkedin.com/in/john-doe"
|
||||
{...register("linkedin")}
|
||||
/>
|
||||
</div>
|
||||
{errors.linkedin && <p className="input-error">
|
||||
{errors.linkedin.message}
|
||||
</p>}
|
||||
<p className="text-body5 mt-16 font-medium">
|
||||
Lightning address
|
||||
</p>
|
||||
|
||||
<div className="input-wrapper mt-8 relative">
|
||||
<input
|
||||
|
||||
type='text'
|
||||
className="input-text"
|
||||
placeholder="johndoe@lnd.com"
|
||||
{...register("lightning_address")}
|
||||
/>
|
||||
</div>
|
||||
{errors.lightning_address && <p className="input-error">
|
||||
{errors.lightning_address.message}
|
||||
</p>}
|
||||
<p className="text-body6 text-gray-400 mt-8 max-w-[70ch]">
|
||||
Your lightning address is used to send the votes you get on your posts, comments, apps...etc, directly to you.
|
||||
</p>
|
||||
<div className="mt-24 flex gap-16 justify-end">
|
||||
<Button
|
||||
color='gray'
|
||||
disabled={mutationStatus.loading}
|
||||
onClick={onClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
type='submit'
|
||||
color='primary'
|
||||
isLoading={mutationStatus.loading}
|
||||
disabled={mutationStatus.loading}
|
||||
>
|
||||
Save changes
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user