Skip to content

Commit

Permalink
multiple changes
Browse files Browse the repository at this point in the history
  • Loading branch information
bhavyagor12 committed Jun 29, 2024
1 parent bb87c9e commit e444ac6
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 59 deletions.
4 changes: 2 additions & 2 deletions packages/nextjs/app/dashboard/[productID]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import { ProvideProduct } from "~~/providers/ProductProvider";
const Product: NextPage = () => {
return (
<ProvideProduct>
<div className="grid grid-cols-6 gap-4 pt-2">
<div className="grid grid-cols-6 gap-4 ">
<div className="col-span-1">
<FrameSidebar />
</div>
<div className="col-span-3">
<div className="col-span-3 mt-24">
<FrameRender />
</div>
<div className="col-span-2 ">
Expand Down
23 changes: 10 additions & 13 deletions packages/nextjs/components/ButtonsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,11 @@ import { FrameButtonMetadata, FrameMetadataType } from "@coinbase/onchainkit";
import { IconButton } from "@mui/material";
import { PlusIcon } from "@heroicons/react/24/outline";
import { useProductJourney } from "~~/providers/ProductProvider";
import { saveFrame } from "~~/services/frames";
import { notification } from "~~/utils/scaffold-eth";

const ButtonList = () => {
const { currentFrame, setCurrentFrame, frame } = useProductJourney();

const { currentFrame, setCurrentFrame, frame, saveFrame } = useProductJourney();
const [activeButtonIndex, setActiveButtonIndex] = useState<number>(0);
useEffect(() => {
console.log("currentFrame", currentFrame);
console.log(activeButtonIndex);
console.log(currentFrame?.buttons[activeButtonIndex]);
}, [currentFrame, activeButtonIndex]);

if (!currentFrame) return null;
const handleAddButton = () => {
Expand All @@ -39,12 +32,11 @@ const ButtonList = () => {

const handleSaveFrame = async () => {
notification.info("Frame saved successfully");
const updatedFrame = await saveFrame({
await saveFrame.mutateAsync({
_id: frame?._id as string,
name: frame?.name as string,
frameJson: currentFrame as FrameMetadataType,
});
console.log(updatedFrame);
};

const handleSave = (button: FrameButtonMetadata) => {
Expand Down Expand Up @@ -100,9 +92,14 @@ const ButtonList = () => {
{currentFrame?.buttons[activeButtonIndex] && (
<ButtonEditor button={currentFrame.buttons[activeButtonIndex]} onSave={handleSave} onDelete={handleDelete} />
)}
<button onClick={handleSaveFrame} className="btn btn-secondary w-full mt-2 flex items-center justify-center">
Save Frame
</button>
<div className="flex items-center">
<button onClick={handleSaveFrame} className="btn btn-error mt-2 flex items-center justify-center">
Delete Frame
</button>
<button onClick={handleSaveFrame} className="btn btn-success mt-2 flex items-center justify-center">
Save Frame
</button>
</div>
</div>
);
};
Expand Down
17 changes: 1 addition & 16 deletions packages/nextjs/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,5 @@
import React from "react";
import { hardhat } from "viem/chains";
import { SwitchTheme } from "~~/components/SwitchTheme";
import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";

/**
* Site footer
*/
export const Footer = () => {
const { targetNetwork } = useTargetNetwork();
const isLocalNetwork = targetNetwork.id === hardhat.id;

return (
<div className="min-h-0 py-5 px-1 mb-11 lg:mb-0">
<div className="fixed flex justify-between items-center w-full z-10 p-4 bottom-0 left-0 pointer-events-none">
<SwitchTheme className={`pointer-events-auto ${isLocalNetwork ? "self-end md:self-auto" : ""}`} />
</div>
</div>
);
return <div className="min-h-0 py-5 px-1 mb-11 lg:mb-0"></div>;
};
2 changes: 1 addition & 1 deletion packages/nextjs/components/FrameEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const FrameEditor = () => {
const [imageUrlOption, setImageUrlOption] = useState("url");
if (!currentFrame) return null;
return (
<div className="p-6 h-[100vh] bg-white rounded-md shadow-md flex flex-col gap-4">
<div className="bg-white flex flex-col gap-4 p-4">
<label htmlFor="imageInput" className="block text-sm font-medium text-gray-700">
Image/HTML{" "}
</label>
Expand Down
6 changes: 2 additions & 4 deletions packages/nextjs/components/FrameRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,17 @@ function FrameRender() {
gap: "4px",
}}
>
{currentFrame.buttons?.map(({ label, action }, index: number) => (
{currentFrame.buttons?.map(({ label }, index: number) => (
<button
type="button"
className={`bg-gray-200 p-1 hover:bg-gray-300 `}
className="btn bg-black rounded-md text-white px-4 py-2"
style={{
flex: "1 1 0px",
cursor: "pointer",
}}
key={index}
>
{action === "mint" ? `♦ ` : ""}
{label}
{action === "post_redirect" || action === "link" ? ` ↗` : ""}
</button>
))}
</div>
Expand Down
43 changes: 33 additions & 10 deletions packages/nextjs/components/FramesSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { useEffect, useMemo, useState } from "react";
import { useEffect, useState } from "react";
import { DEFAULT_FRAME } from "~~/constants";
import { useProductJourney } from "~~/providers/ProductProvider";
import { getFrameById } from "~~/services/frames";
import { Frame } from "~~/types/commontypes";

function FrameSidebar() {
const { frames: dbFrames } = useProductJourney();
const [currentFrameId, setCurrentFrameId] = useState<string>("");
const { frames: dbFrames, setFrame, setCurrentFrame, createFrame } = useProductJourney();
const [frames, setFrames] = useState<Frame[] | undefined>(undefined);
useEffect(() => {
if (dbFrames) {
Expand All @@ -13,16 +15,37 @@ function FrameSidebar() {
.catch(error => console.error("Error fetching frames:", error));
}
}, [dbFrames]);
const onCreate = async () => {
await createFrame.mutateAsync({
name: "Frame",
frameJson: DEFAULT_FRAME,
});
};
if (!frames) return null;
return (
<div className="bg-white flex flex-col gap-2">
{frames.map((frame, index) => (
<div key={index} className="border-2 border-black">
<h3>{frame.name}</h3>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={frame.frameJson.image?.src} alt={frame.name} />
</div>
))}
<div className="bg-white flex flex-col gap-2 p-4 h-full">
<div className="flex flex-wrap gap-2 h-[600px] overflow-y-scroll">
{frames.map((frame, index) => (
<div
key={index}
className={`border-2 p-2 w-full h-40 flex flex-col items-center justify-center ${currentFrameId === frame._id ? 'border-blue-500' : 'border-black'}`}
onClick={() => {
setCurrentFrameId(frame._id as string);
setFrame(frame);
setCurrentFrame(frame.frameJson);
}}
>
<h3 className="text-center text-sm">{frame.name}</h3>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={frame.frameJson.image?.src} alt={frame.name} className="w-32 h-auto" />
</div>
))}
</div>
<div className="mt-auto flex justify-center w-full">
<button onClick={onCreate} className="btn btn-primary w-full">
Create
</button>
</div>
</div>
);
}
Expand Down
101 changes: 88 additions & 13 deletions packages/nextjs/providers/ProductProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { PropsWithChildren, createContext, useContext, useEffect, useMemo, useSt
import { useParams } from "next/navigation";
import { FrameMetadataType } from "@coinbase/onchainkit";
import { UseMutationResult, UseQueryResult, useMutation, useQuery } from "@tanstack/react-query";
import { DEFAULT_FRAME } from "~~/constants";
import { getFrameById } from "~~/services/frames";
import { Frame, Journey } from "~~/types/commontypes";

Expand All @@ -16,6 +15,9 @@ interface IProductJourney {
frames: string[] | undefined;
setCurrentFrame: (frame: FrameMetadataType) => void;
currentFrame: FrameMetadataType | null;
createFrame: UseMutationResult<Frame, Error, Omit<Frame, "_id">>;
saveFrame: UseMutationResult<Frame, Error, Frame>;
deleteFrame: UseMutationResult<Frame, Error, Frame>;
}

const ProductJourney = createContext<IProductJourney | null>(null);
Expand All @@ -26,15 +28,8 @@ const useProduct = () => {
return params.productID as string;
}, [params.productID]);
const [journey, setJourney] = useState<Journey | null>(null);
const [frame, setFrame] = useState<Frame | null>({
_id: "",
name: "",
frameJson: DEFAULT_FRAME,
});
const [frame, setFrame] = useState<Frame | null>(null);
const [currentFrame, setCurrentFrame] = useState<FrameMetadataType | null>(null);
const frames = useMemo(() => {
return journey?.frames;
}, [journey]);

const productQuery = useQuery({
queryKey: ["product", productID],
Expand All @@ -60,22 +55,99 @@ const useProduct = () => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
const data = await response.json();
return data;
},
onSuccess: () => {
productQuery.refetch();
},
onSettled: data => {
setJourney(data);
},
});

useEffect(() => {
if (!productQuery.data) return;
setJourney(productQuery.data);
console.log(productQuery.data);
if (frame || !productQuery.data.frames) return;
getFrameById(productQuery.data.frames[0]).then(frame => {
setFrame(frame);
setCurrentFrame(frame.frameJson);
});
}, [productQuery.data]);
}, [frame, productQuery.data]);

const createFrame = useMutation({
mutationFn: async (frame: Omit<Frame, "_id">) => {
const response = await fetch(`/api/frame`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(frame),
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
return data;
},
onSettled: data => {
console.log(data);
journey?.frames.push(data._id);
updateProduct.mutateAsync(journey as Journey);
setFrame(data);
setCurrentFrame(data.frameJson);
},
});

const saveFrame = useMutation({
mutationFn: async (frame: Frame) => {
const response = await fetch(`/api/frame/${frame._id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(frame),
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
return data;
},
onSettled: data => {
setFrame(data);
setCurrentFrame(data.frameJson);
productQuery.refetch();
},
});

const deleteFrame = useMutation({
mutationFn: async (frame: Frame) => {
const response = await fetch(`/api/frame/${frame._id}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
const newFrames = journey?.frames.filter(f => f !== frame._id);
if (!newFrames || !journey) return;
journey.frames = newFrames;
await updateProduct.mutateAsync(journey);
const data = await response.json();
return data;
},
onSettled: () => {
console.log("Frame deleted");
},
});
const frames = useMemo(() => {
if (!journey) return;
return journey?.frames;
}, [journey]);

return {
productID,
Expand All @@ -87,12 +159,15 @@ const useProduct = () => {
setCurrentFrame,
journey,
frames,
createFrame,
saveFrame,
deleteFrame,
};
};

export function ProvideProduct({ children }: PropsWithChildren<any>) {
const value = useProduct();
return <ProductJourney.Provider value={value}>{children}</ProductJourney.Provider>;
return <ProductJourney.Provider value={value}> {children}</ProductJourney.Provider>;
}

export const useProductJourney = () => {
Expand Down

0 comments on commit e444ac6

Please sign in to comment.