+
diff --git a/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx b/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx
new file mode 100644
index 0000000..f76e3b8
--- /dev/null
+++ b/src/features/Profiles/pages/EditProfilePage/EditProfilePage.tsx
@@ -0,0 +1,79 @@
+import { Navigate, NavLink, Route, Routes } from "react-router-dom";
+import LoadingPage from "src/Components/LoadingPage/LoadingPage";
+import NotFoundPage from "src/features/Shared/pages/NotFoundPage/NotFoundPage";
+import { useProfileQuery } from "src/graphql";
+import { useAppSelector } from "src/utils/hooks";
+import CommentsSettingsCard from "../ProfilePage/CommentsSettingsCard/CommentsSettingsCard";
+import UpdateMyProfileCard from "./UpdateMyProfileCard/UpdateMyProfileCard";
+import { Helmet } from 'react-helmet'
+
+
+const links = [
+ {
+ text: "👾 My Profile",
+ path: 'my-profile',
+ },
+ {
+ text: "⚙️ Preferences",
+ path: 'preferences',
+ }
+]
+
+
+
+export default function EditProfilePage() {
+ const userId = useAppSelector(state => state.user.me?.id)
+ const profileQuery = useProfileQuery({
+ variables: {
+ profileId: userId!,
+ },
+ skip: !userId,
+ })
+
+
+
+
+ if (!userId || profileQuery.loading)
+ return
+
+ if (!profileQuery.data?.profile)
+ return
+
+ return (
+ <>
+
+ Settings
+
+
+
+
+
+
+ } />
+ } />
+
+ } />
+
+
+
+ >
+ )
+}
diff --git a/src/features/Profiles/pages/EditProfilePage/UpdateMyProfileCard/UpdateMyProfileCard.tsx b/src/features/Profiles/pages/EditProfilePage/UpdateMyProfileCard/UpdateMyProfileCard.tsx
new file mode 100644
index 0000000..b0d9c5f
--- /dev/null
+++ b/src/features/Profiles/pages/EditProfilePage/UpdateMyProfileCard/UpdateMyProfileCard.tsx
@@ -0,0 +1,287 @@
+import { SubmitHandler, useForm } from "react-hook-form"
+import Button from "src/Components/Button/Button";
+import { User, useUpdateProfileAboutMutation } from "src/graphql";
+import { NotificationsService } from "src/services/notifications.service";
+import * as yup from "yup";
+import { yupResolver } from "@hookform/resolvers/yup";
+import Avatar from "src/features/Profiles/Components/Avatar/Avatar";
+
+
+
+interface Props {
+ data: Pick
,
+ onClose?: () => void;
+}
+
+type IFormInputs = Props['data'];
+
+const schema: yup.SchemaOf = 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 UpdateMyProfileCard({ data, onClose }: Props) {
+
+ const { register, formState: { errors }, handleSubmit } = useForm({
+ defaultValues: data,
+ resolver: yupResolver(schema),
+ mode: 'onBlur',
+ });
+
+ const [mutate, mutationStatus] = useUpdateProfileAboutMutation({
+ onCompleted: () => {
+ onClose?.()
+ }
+ });
+
+
+
+ const onSubmit: SubmitHandler = 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 (
+
+ )
+}
diff --git a/src/features/Profiles/pages/ProfilePage/updateProfile.graphql b/src/features/Profiles/pages/EditProfilePage/UpdateMyProfileCard/updateProfile.graphql
similarity index 100%
rename from src/features/Profiles/pages/ProfilePage/updateProfile.graphql
rename to src/features/Profiles/pages/EditProfilePage/UpdateMyProfileCard/updateProfile.graphql
diff --git a/src/styles/index.scss b/src/styles/index.scss
index 47d47a1..96fdc2e 100644
--- a/src/styles/index.scss
+++ b/src/styles/index.scss
@@ -2,7 +2,8 @@
$screen-xs-min: 320px;
-@import "./tw.scss", "./shared.scss", "./vendors.scss", "./scrollbar.scss";
+@import "./tw.scss", "./shared.scss", "./vendors.scss", "./scrollbar.scss",
+ "./ui_state.scss";
@import "/src/styles/mixins/index.scss";
html {
diff --git a/src/styles/shared.scss b/src/styles/shared.scss
index a61b964..6441768 100644
--- a/src/styles/shared.scss
+++ b/src/styles/shared.scss
@@ -1,15 +1,21 @@
.input-removed-arrows::-webkit-outer-spin-button,
.input-removed-arrows::-webkit-inner-spin-button {
- -webkit-appearance: none;
- margin: 0;
+ -webkit-appearance: none;
+ margin: 0;
}
/* Firefox */
.input-removed-arrows[type="number"] {
- -moz-appearance: textfield;
+ -moz-appearance: textfield;
}
-button[disabled]{
- opacity: .5;
- pointer-events: none;
-}
\ No newline at end of file
+button[disabled] {
+ opacity: 0.5;
+ pointer-events: none;
+}
+
+.sticky-side-element {
+ position: sticky;
+ top: calc(var(--navHeight) + 16px);
+ max-height: calc(100vh - var(--navHeight) - 16px);
+}
diff --git a/src/styles/ui_state.scss b/src/styles/ui_state.scss
new file mode 100644
index 0000000..3f8527f
--- /dev/null
+++ b/src/styles/ui_state.scss
@@ -0,0 +1,3 @@
+:root {
+ --navHeight: 0;
+}
diff --git a/src/utils/hooks/useResizeListener.ts b/src/utils/hooks/useResizeListener.ts
index 07dd7fd..356e1a9 100644
--- a/src/utils/hooks/useResizeListener.ts
+++ b/src/utils/hooks/useResizeListener.ts
@@ -1,5 +1,5 @@
import { useDebouncedCallback } from "@react-hookz/web";
-import { useEffect } from "react";
+import { useCallback, useEffect } from "react";
export const useResizeListener = (
listener: () => void,
@@ -7,7 +7,7 @@ export const useResizeListener = (
) => {
options.debounce = options.debounce ?? 250;
- const func = useDebouncedCallback(listener, [], options.debounce)
+ const func = useDebouncedCallback(listener, [listener], options.debounce)
useEffect(() => {
window.addEventListener("resize", func);
diff --git a/src/utils/routing/routes.ts b/src/utils/routing/routes.ts
index 372a9b2..5f7f696 100644
--- a/src/utils/routing/routes.ts
+++ b/src/utils/routing/routes.ts
@@ -78,6 +78,7 @@ export const PAGES_ROUTES = {
default: "/donate"
},
profile: {
+ editProfile: "/edit-profile/*",
byId: "/profile/:id/*",
},
auth: {