Skip to content

Commit

Permalink
homogenizes form and profile sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
andresgnlez committed Dec 18, 2024
1 parent be3da98 commit ce15d10
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 73 deletions.
26 changes: 14 additions & 12 deletions client/src/containers/profile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useEffect, useMemo, useRef } from "react";

import Link from "next/link";

import { useSetAtom } from "jotai";
import { ExtractAtomValue, useSetAtom } from "jotai";

import { useFeatureFlags } from "@/hooks/use-feature-flags";

Expand All @@ -14,13 +14,13 @@ import FileUpload, { TEMPLATE_FILES } from "@/containers/profile/file-upload";
import FileUploadDescription from "@/containers/profile/file-upload/description";
import ProfileSection from "@/containers/profile/profile-section";
import ProfileSidebar from "@/containers/profile/profile-sidebar";
import { intersectingAtom } from "@/containers/profile/store";
import { profileStepAtom } from "@/containers/profile/store";
import UserDetails from "@/containers/profile/user-details";

import { ScrollArea } from "@/components/ui/scroll-area";
import { SidebarTrigger } from "@/components/ui/sidebar";

const sections = [
export const PROFILE_SECTIONS = [
{
id: "my-details",
title: "My details",
Expand Down Expand Up @@ -58,10 +58,10 @@ const sections = [

export default function Profile() {
const ref = useRef<HTMLDivElement>(null);
const setIntersecting = useSetAtom(intersectingAtom);
const setProfileStep = useSetAtom(profileStepAtom);
const featureFlags = useFeatureFlags();
const currentSections = useMemo(() => {
return sections.filter((section) => {
return PROFILE_SECTIONS.filter((section) => {
const featureFlagExists = section.id in featureFlags;
const isFeatureEnabled =
featureFlagExists &&
Expand All @@ -78,9 +78,11 @@ export default function Profile() {
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const sectionSlug = entry.target.id;
const sectionSlug = entry.target.id as ExtractAtomValue<
typeof profileStepAtom
>;

setIntersecting(sectionSlug);
setProfileStep(sectionSlug);
}
});
},
Expand All @@ -95,22 +97,22 @@ export default function Profile() {
},
);

const sections = Array.from(
const PROFILE_SECTIONS = Array.from(
ref.current.querySelector("#profile-sections-container")?.children || [],
);
sections.forEach((section) => observer.observe(section));
PROFILE_SECTIONS.forEach((section) => observer.observe(section));

return () => observer.disconnect();
}, [setIntersecting]);
}, [setProfileStep]);

return (
<div className="flex h-lvh w-full flex-col">
<div className="flex items-center space-x-2 p-4">
<div className="flex h-16 items-center space-x-2 p-4 pl-0">
<SidebarTrigger />
<h2 className="text-2xl font-medium">User area</h2>
</div>

<div className="relative grid h-full grid-cols-[317px_1fr] gap-6 overflow-hidden pl-4">
<div className="relative grid h-full grid-cols-[317px_1fr] gap-6 overflow-hidden">
<ProfileSidebar
navItems={currentSections.map((s) => ({ id: s.id, name: s.title }))}
/>
Expand Down
36 changes: 17 additions & 19 deletions client/src/containers/profile/profile-sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import { signOut, useSession } from "next-auth/react";

import { client } from "@/lib/query-client";
import { queryKeys } from "@/lib/query-keys";
import { cn } from "@/lib/utils";

import { intersectingAtom } from "@/containers/profile/store";
import { profileStepAtom } from "@/containers/profile/store";

import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
Expand Down Expand Up @@ -45,7 +44,7 @@ const ProfileSidebar: FC<ProfileSidebarProps> = ({ navItems }) => {
queryKey: queryKeys.user.me(session?.user?.id as string).queryKey,
},
);
const intersecting = useAtomValue(intersectingAtom);
const intersecting = useAtomValue(profileStepAtom);

return (
<aside className="flex h-full flex-col gap-8 pb-6 pt-3">
Expand All @@ -62,27 +61,26 @@ const ProfileSidebar: FC<ProfileSidebarProps> = ({ navItems }) => {
<h2 id="sidebar-nav-title" className="sr-only">
User area navigation
</h2>
<ol role="list" className="space-y-2">
<ul role="list" className="space-y-2">
{navItems.map((o) => (
<li key={`section-link-${o.id}`} role="listitem">
<Link
className={cn(
"block rounded-3xl text-sm font-semibold text-muted-foreground transition-colors hover:bg-big-stone-900",
intersecting === o.id && [
"bg-accent text-accent-foreground",
"hover:bg-accent hover:text-accent-foreground",
],
)}
href={`#${o.id}`}
id={getSidebarLinkId(o.id)}
aria-controls={o.id}
aria-current={intersecting === o.id ? "true" : undefined}
<Button
variant={intersecting === o.id ? "default" : "ghost"}
asChild
className="w-full justify-start font-medium"
>
<div className="px-4 py-2">{o.name}</div>
</Link>
<Link
href={`#${o.id}`}
id={getSidebarLinkId(o.id)}
aria-controls={o.id}
aria-current={intersecting === o.id ? "true" : undefined}
>
{o.name}
</Link>
</Button>
</li>
))}
</ol>
</ul>
</nav>
<Button
variant="outline"
Expand Down
6 changes: 5 additions & 1 deletion client/src/containers/profile/store.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { atom } from "jotai";

export const intersectingAtom = atom<string | null>(null);
import { PROFILE_SECTIONS } from "@/containers/profile";

export const profileStepAtom = atom<
(typeof PROFILE_SECTIONS)[number]["id"] | null
>(null);
2 changes: 0 additions & 2 deletions client/src/containers/projects/form/assumptions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ export default function AssumptionsProjectForm() {
},
);

// const c = useMemo(() => COLUMNS(), []);

const table = useReactTable({
// @ts-expect-error fix later
data: isSuccess ? data : NO_DATA,
Expand Down
41 changes: 35 additions & 6 deletions client/src/containers/projects/form/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useFormContext } from "react-hook-form";
import { useFormContext, useWatch } from "react-hook-form";

import { ACTIVITY } from "@shared/entities/activity.enum";

Expand All @@ -8,27 +8,56 @@ import RestorationPlanProjectForm from "@/containers/projects/form/restoration-p
import SetupProjectForm, {
CreateCustomProjectForm,
} from "@/containers/projects/form/setup";
import {
PROJECT_SETUP_STEPS,
RESTORATION_STEPS,
} from "@/containers/projects/new/sidebar";

import { Card } from "@/components/ui/card";

export const useFormValues = () => {
const { getValues } = useFormContext<CreateCustomProjectForm>();

return {
...getValues(),
...useWatch(),
};
};

export default function ProjectForm({ onSubmit }: { onSubmit: () => void }) {
const form = useFormContext<CreateCustomProjectForm>();
const { activity } = form.getValues();

return (
<form className="w-full space-y-8" onSubmit={onSubmit}>
<div className="flex flex-col gap-3">
<Card className="flex flex-1 flex-col" variant="secondary">
<div className="flex flex-col gap-3" id="custom-project-steps-container">
<Card
className="flex flex-1 flex-col"
variant="secondary"
id={PROJECT_SETUP_STEPS[0].slug}
>
<SetupProjectForm />
</Card>
<Card className="flex flex-1 flex-col" variant="secondary">
<Card
className="flex flex-1 flex-col"
variant="secondary"
id={PROJECT_SETUP_STEPS[1].slug}
>
<AssumptionsProjectForm />
</Card>
<Card className="flex flex-1 flex-col" variant="secondary">
<Card
className="flex flex-1 flex-col"
variant="secondary"
id={PROJECT_SETUP_STEPS[2].slug}
>
<CostInputsOverridesProjectForm />
</Card>
{activity === ACTIVITY.RESTORATION && (
<Card className="flex flex-1 flex-col" variant="secondary">
<Card
className="flex flex-1 flex-col"
variant="secondary"
id={RESTORATION_STEPS[0].slug}
>
<RestorationPlanProjectForm />
</Card>
)}
Expand Down
16 changes: 3 additions & 13 deletions client/src/containers/projects/form/restoration-plan/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useMemo } from "react";

import { useFormContext, useWatch } from "react-hook-form";
import { useFormContext } from "react-hook-form";

import {
flexRender,
Expand All @@ -11,6 +11,7 @@ import {
import { client } from "@/lib/query-client";
import { queryKeys } from "@/lib/query-keys";

import { useFormValues } from "@/containers/projects/form";
import { COLUMNS } from "@/containers/projects/form/restoration-plan/columns";
import { CreateCustomProjectForm } from "@/containers/projects/form/setup";

Expand All @@ -29,20 +30,9 @@ import {
TableRow,
} from "@/components/ui/table";

const useFormValues = () => {
const { getValues } = useFormContext<CreateCustomProjectForm>();

return {
...getValues(),
...useWatch(),
};
};

export default function RestorationPlanProjectForm() {
const form = useFormContext<CreateCustomProjectForm>();

const formValues = useFormValues();

const {
ecosystem,
activity,
Expand All @@ -55,7 +45,7 @@ export default function RestorationPlanProjectForm() {
// @ts-expect-error fix later
restorationYearlyBreakdown,
},
} = formValues;
} = useFormValues();

const { queryKey } = queryKeys.customProjects.assumptions({
ecosystem,
Expand Down
2 changes: 1 addition & 1 deletion client/src/containers/projects/new/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default function Header() {
const router = useRouter();

return (
<div className="flex items-center justify-between py-3 pr-6">
<div className="flex h-16 items-center justify-between py-3 pr-6">
<div className="flex items-center space-x-2">
<SidebarTrigger />
<h2 className="text-2xl font-medium">Custom project</h2>
Expand Down
40 changes: 39 additions & 1 deletion client/src/containers/projects/new/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"use client";

import { useEffect, useRef } from "react";

import { FormProvider, useForm } from "react-hook-form";

import { zodResolver } from "@hookform/resolvers/zod";
Expand All @@ -15,6 +17,7 @@ import {
CreateCustomProjectSchema,
LOSS_RATE_USED,
} from "@shared/schemas/custom-projects/create-custom-project.schema";
import { ExtractAtomValue, useSetAtom } from "jotai";

import { client } from "@/lib/query-client";
import { queryKeys } from "@/lib/query-keys";
Expand All @@ -25,6 +28,7 @@ import ProjectForm from "@/containers/projects/form";
import { CreateCustomProjectForm } from "@/containers/projects/form/setup";
import Header from "@/containers/projects/new/header";
import ProjectSidebar from "@/containers/projects/new/sidebar";
import { formStepAtom } from "@/containers/projects/store";

import { ScrollArea } from "@/components/ui/scroll-area";

Expand Down Expand Up @@ -144,6 +148,9 @@ export const onSubmit = async (data: CreateCustomProjectForm) => {
};

export default function CreateCustomProject() {
const ref = useRef<HTMLDivElement>(null);
const setIntersecting = useSetAtom(formStepAtom);

const { queryKey } = queryKeys.customProjects.countries;
const { data: countryOptions } =
client.customProjects.getAvailableCountries.useQuery(
Expand Down Expand Up @@ -192,12 +199,43 @@ export default function CreateCustomProject() {
},
mode: "all",
});
const activity = methods.watch("activity");

useEffect(() => {
if (!ref.current) return;

const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const sectionSlug = entry.target.id as ExtractAtomValue<
typeof formStepAtom
>;

setIntersecting(sectionSlug);
}
});
},
{
root: ref.current,
threshold: 0.4,
},
);

const sections = Array.from(
ref.current.querySelector("#custom-project-steps-container")?.children ||
[],
);
sections.forEach((section) => observer.observe(section));

return () => observer.disconnect();
}, [setIntersecting, activity]);

return (
<FormProvider {...methods}>
<div className="flex flex-1 flex-col">
<Header />
<div className="flex flex-1 gap-3 overflow-hidden">
<div className="flex flex-1 gap-3 overflow-hidden" ref={ref}>
<ProjectSidebar />
<div className="mb-4 flex-1">
<ScrollArea className="flex h-full gap-3 pr-6">
Expand Down
Loading

0 comments on commit ce15d10

Please sign in to comment.