feat(resume): implement resume locking feature

This commit is contained in:
Amruth Pillai
2023-11-06 13:57:12 +01:00
parent 9a0402d525
commit 015e284318
23 changed files with 288 additions and 83 deletions

View File

@ -1,6 +1,6 @@
import { HouseSimple, SidebarSimple } from "@phosphor-icons/react";
import { HouseSimple, Lock, SidebarSimple } from "@phosphor-icons/react";
import { useBreakpoint } from "@reactive-resume/hooks";
import { Button } from "@reactive-resume/ui";
import { Button, Tooltip } from "@reactive-resume/ui";
import { cn } from "@reactive-resume/utils";
import { Link } from "react-router-dom";
@ -11,8 +11,10 @@ export const BuilderHeader = () => {
const { isDesktop } = useBreakpoint();
const defaultPanelSize = isDesktop ? 25 : 0;
const toggle = useBuilderStore((state) => state.toggle);
const title = useResumeStore((state) => state.resume.title);
const locked = useResumeStore((state) => state.resume.locked);
const toggle = useBuilderStore((state) => state.toggle);
const isDragging = useBuilderStore(
(state) => state.panel.left.isDragging || state.panel.right.isDragging,
);
@ -48,6 +50,12 @@ export const BuilderHeader = () => {
<span className="mr-2 text-xs opacity-40">{"/"}</span>
<h1 className="font-medium">{title}</h1>
{locked && (
<Tooltip content="This resume is locked, please unlock to make further changes.">
<Lock size={14} className="ml-2 opacity-75" />
</Tooltip>
)}
</div>
<Button size="icon" variant="ghost" onClick={() => onToggle("right")}>

View File

@ -2,9 +2,9 @@ import {
ArrowCounterClockwise,
Broom,
Columns,
DotsThreeVertical,
Eye,
EyeSlash,
List,
PencilSimple,
Plus,
TrashSimple,
@ -55,7 +55,7 @@ export const SectionOptions = ({ id }: Props) => {
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<DotsThreeVertical weight="bold" />
<List weight="bold" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-48">

View File

@ -7,6 +7,7 @@ import { ThemeSwitch } from "@/client/components/theme-switch";
import { ExportSection } from "./sections/export";
import { InformationSection } from "./sections/information";
import { LayoutSection } from "./sections/layout";
import { NotesSection } from "./sections/notes";
import { PageSection } from "./sections/page";
import { SharingSection } from "./sections/sharing";
import { StatisticsSection } from "./sections/statistics";
@ -43,6 +44,8 @@ export const RightSidebar = () => {
<Separator />
<ExportSection />
<Separator />
<NotesSection />
<Separator />
<InformationSection />
<Separator />
<Copyright className="text-center" />
@ -63,6 +66,18 @@ export const RightSidebar = () => {
<SectionIcon id="theme" name="Theme" onClick={() => scrollIntoView("#theme")} />
<SectionIcon id="page" name="Page" onClick={() => scrollIntoView("#page")} />
<SectionIcon id="sharing" name="Sharing" onClick={() => scrollIntoView("#sharing")} />
<SectionIcon
id="statistics"
name="Statistics"
onClick={() => scrollIntoView("#statistics")}
/>
<SectionIcon id="export" name="Export" onClick={() => scrollIntoView("#export")} />
<SectionIcon id="notes" name="Notes" onClick={() => scrollIntoView("#notes")} />
<SectionIcon
id="information"
name="Information"
onClick={() => scrollIntoView("#information")}
/>
</div>
<ThemeSwitch size={14} />

View File

@ -0,0 +1,37 @@
import { RichInput } from "@reactive-resume/ui";
import { useResumeStore } from "@/client/stores/resume";
import { getSectionIcon } from "../shared/section-icon";
export const NotesSection = () => {
const setValue = useResumeStore((state) => state.setValue);
const notes = useResumeStore((state) => state.resume.data.metadata.notes);
return (
<section id="notes" className="grid gap-y-6">
<header className="flex items-center justify-between">
<div className="flex items-center gap-x-4">
{getSectionIcon("notes")}
<h2 className="line-clamp-1 text-3xl font-bold">Notes</h2>
</div>
</header>
<main className="grid gap-y-4">
<p className="leading-relaxed">
This section is reserved for your personal notes specific to this resume. The content here
remains private and is not shared with anyone else.
</p>
<div className="space-y-1.5">
<RichInput content={notes} onChange={(content) => setValue("metadata.notes", content)} />
<p className="text-xs leading-relaxed opacity-75">
For example, information regarding which companies you sent this resume to or the links
to the job descriptions can be noted down here.
</p>
</div>
</main>
</section>
);
};

View File

@ -4,6 +4,7 @@ import {
IconProps,
Info,
Layout,
Note,
Palette,
ReadCvLogo,
ShareFat,
@ -13,6 +14,7 @@ import {
import { Button, ButtonProps, Tooltip } from "@reactive-resume/ui";
export type MetadataKey =
| "notes"
| "template"
| "layout"
| "typography"
@ -26,6 +28,8 @@ export type MetadataKey =
export const getSectionIcon = (id: MetadataKey, props: IconProps = {}) => {
switch (id) {
// Left Sidebar
case "notes":
return <Note size={18} {...props} />;
case "template":
return <DiamondsFour size={18} {...props} />;
case "layout":