Skip to content

Commit

Permalink
register schema form and displaying schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
RojhatToptamus committed Jun 23, 2024
1 parent ae242c2 commit 4b54855
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 164 deletions.
151 changes: 80 additions & 71 deletions packages/nextjs/app/dashboard/schemas/page.tsx
Original file line number Diff line number Diff line change
@@ -1,72 +1,65 @@
"use client";
import React, { useState, useEffect } from "react";
import Link from "next/link";
import { fetchAllSchemas, fetchStats, shortAddress } from "~~/utils/utils";
import { useScaffoldEventHistory } from "~~/hooks/scaffold-stark/useScaffoldEventHistory";
import Modal from "~~/components/Modal";
import RegisterSchemaForm from "~~/components/forms/RegisterSchemaForm";
const Dashboard = () => {

const Schemas = () => {
const [totalSchemas, setTotalSchemas] = useState<number>(0);
const [schemas, setSchemas] = useState<any[]>([]);
const [stats, setStats] = useState<{
totalAtestations: number;
totalSchemas: number;
totalAttestors: number;
}>({
totalAtestations: 0,
totalSchemas: 0,
totalAttestors: 0,

const {
data: eventData,
isLoading,
error: err,
} = useScaffoldEventHistory({
contractName: "SchemaRegistry",
eventName: "contracts::SchemaRegistry::SchemaRegistry::Registered",
fromBlock: BigInt(0),
blockData: true,
transactionData: false,
receiptData: false,
watch: true,
enabled: true,
});

const getAllSchemas = async () => {
try {
const schemaData = await fetchAllSchemas();
const stats = await fetchStats();
setSchemas(schemaData);
setStats(stats);
} catch (error) {
console.error("Error fetching schemas:", error);
useEffect(() => {
if (eventData) {
setTotalSchemas(eventData.length);
setSchemas(
eventData.map((event) => ({
uid: event.args.uid,
schema: event.args.schema_record,
caller: event.args.caller,
})),
);
}
};
}, [eventData]);

const SchemaLink = ({ uid }: { uid: string }) => (
<Link href={`/dashboard/schema/${uid}`} className="text-[#495FA9]">
{shortAddress(uid)}
{uid.toString()}
</Link>
);

const DashboardStats = ({
totalAtestations,
totalSchemas,
totalAttestors,
}: {
totalAtestations: number;
totalSchemas: number;
totalAttestors: number;
}) => (
const DashboardStats = ({ totalSchemas }: { totalSchemas: number }) => (
<div className="flex justify-around mb-6">
<div className="text-center">
<div className="text-3xl font-bold text-[#495FA9]">
{totalAtestations}
</div>
<div className="text-gray-600">Total Schemas</div>
</div>
<div className="text-center">
<div className="text-3xl font-bold text-[#495FA9]">{totalSchemas}</div>
<div className="text-gray-600">Total Schemas</div>
</div>
</div>
);

useEffect(() => {
getAllSchemas();
}, []);
return (
<div>
<div className="p-4 bg-[#E9E9F6]">
<div className=" p-6 rounded-lg shadow-md">
<div className="p-6 rounded-lg shadow-md">
<div className="flex justify-between items-center mb-6">
<div>
<h1 className="text-2xl font-bold text-[#495FA9]">
Attestation Scan
Solas Schemas
</h1>
<p className="text-gray-600">
Showing the most recent Solas Schemas.
Expand All @@ -86,37 +79,53 @@ const Dashboard = () => {
<RegisterSchemaForm />
</Modal>
</div>
<DashboardStats
totalAtestations={stats.totalAtestations}
totalSchemas={stats.totalSchemas}
totalAttestors={stats.totalAttestors}
/>
<div className="overflow-x-auto">
<table className="min-w-full bg-white border border-gray-200">
<thead>
<tr className="bg-gray-100 border-b">
<th className="px-4 py-2 text-[#495FA9]">UID</th>
<th className="px-4 py-2 text-[#495FA9]">Schema</th>
<th className="px-4 py-2 text-[#495FA9]">Attestations</th>
</tr>
</thead>
<tbody>
{schemas.map((schema) => (
<tr key={schema.uid} className="border-b">
<td className="px-4 py-2">
<SchemaLink uid={schema.uid} />
</td>
<td className="px-4 py-2 text-[#495FA9]">
{schema.schema}
</td>
<td className="px-4 py-2 text-[#495FA9]">
{schema.attestations}
</td>
<DashboardStats totalSchemas={totalSchemas} />
{isLoading ? (
<div className="flex justify-center items-center">
<svg
aria-hidden="true"
className="w-8 h-8 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600"
viewBox="0 0 100 101"
fill="none"
>
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="rgb(191 219 254)"
/>
<path
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="rgb(59 130 246)"
/>
</svg>
</div>
) : (
<div className="overflow-x-auto">
<table className="min-w-full bg-white border border-gray-200">
<thead>
<tr className="bg-gray-100 border-b">
<th className="px-4 py-2 text-[#495FA9]">UID</th>
<th className="px-4 py-2 text-[#495FA9]">Creator</th>
<th className="px-4 py-2 text-[#495FA9]">Schema Record</th>
</tr>
))}
</tbody>
</table>
</div>
</thead>
<tbody>
{schemas.map((schema, index) => (
<tr key={index} className="border-b">
<td className="px-4 py-2">
<SchemaLink uid={schema.uid} />
</td>
<td className="px-4 py-2 text-[#495FA9]">
{schema.caller}
</td>
<td className="px-4 py-2 text-[#495FA9]">
{schema.schema}
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
<div className="mt-4 text-center">
<a className="text-blue-600" href="/attestations">
View all schemas
Expand All @@ -128,4 +137,4 @@ const Dashboard = () => {
);
};

export default Dashboard;
export default Schemas;
6 changes: 3 additions & 3 deletions packages/nextjs/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ const Home: NextPage = () => {
<div className="flex flex-col bg-base-100 px-10 py-10 text-center items-center max-w-xs rounded-3xl">
<MagnifyingGlassIcon className="h-8 w-8 fill-secondary" />
<p>
Explore your local transactions with the{" "}
<Link href="/blockexplorer" passHref className="link">
Block Explorer
Explore attestation and schemas via the{" "}
<Link href="/dashboard" passHref className="link">
Dashboard
</Link>{" "}
tab.
</p>
Expand Down
16 changes: 9 additions & 7 deletions packages/nextjs/components/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ const Modal: React.FC<ModalProps> = ({ children, trigger }) => {
{trigger({ openModal })}
{isOpen && (
<div className="fixed inset-0 bg-gray-600 bg-opacity-50 flex justify-center items-center p-8 z-50">
<div className="bg-white p-6 rounded-xl shadow-lg w-11/12 max-w-lg">
<div className="bg-white p-6 rounded-xl shadow-lg w-11/12 max-w-lg ">
{children}
<button
className="mt-4 text-gray-500 hover:underline"
onClick={closeModal}
>
Close
</button>
<div className="flex flex-col items-center">
<button
className="mt-4 mx-auto text-gray-500 hover:underline"
onClick={closeModal}
>
Close
</button>
</div>
</div>
</div>
)}
Expand Down
115 changes: 49 additions & 66 deletions packages/nextjs/components/forms/RegisterSchemaForm.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
"use client";
import { useEffect } from "react";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { useScaffoldWriteContract } from "~~/hooks/scaffold-stark/useScaffoldWriteContract";

const RegisterSchemaForm = () => {
const [schema, setSchema] = useState<string>("");
const [revocable, setRevocable] = useState<boolean>(false);
const router = useRouter();

const isPending = false;
const isConfirming = false;
const isConfirmed = false;
const isSuccess = false;
const { writeAsync, isSuccess, isPending, isError } =
useScaffoldWriteContract({
contractName: "SchemaRegistry",
functionName: "register",
args: [schema, false],
});

const handleSubmit = async (formData: FormData) => {
const schema = formData.get("schema") as string;
const revocable = formData.get("revocable") as string;

setSchema(schema);
setRevocable(revocable === "true");
try {
await writeAsync({
args: [schema, true],
});
} catch (err) {
console.error("Error submitting transaction:", err);
}
};

const LoadingSpinner = (
<svg
Expand All @@ -28,87 +48,50 @@ const RegisterSchemaForm = () => {
</svg>
);

useEffect(() => {
if (isConfirmed) {
// redirect to dashboard
setTimeout(() => {
router.push("/dashboard");
}, 5000);
}
}, [isPending, isConfirming, isConfirmed, router]);

const handleSubmit = (formData: FormData) => {
const name = formData.get("name");
const email = formData.get("email");
const profileImage = formData.get("profileImage");
};

return (
<div className="">
<h1 className="text-3xl text-[#495FA9] mb-4">Register Schema</h1>
<form action={handleSubmit} className=" rounded-lg space-y-4">
<h1 className="text-3xl text-[#495FA9] mb-4">Register Schema</h1>
<form action={handleSubmit} className="rounded-lg space-y-4">
<input
type="text"
name="schema"
placeholder="Schema"
required
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
/>
<input
type="text"
<span className="block text-sm text-gray-600">Revocable</span>
<select
name="revocable"
placeholder="Revocable"
required
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
/>
{!isPending && !isConfirming && (
<button
type="submit"
className="w-full bg-[#495FA9] text-white py-2 px-4 rounded-lg hover:bg-[#475299]"
>
Register
</button>
)}
{(isPending || isConfirming) && (
<div className="flex justify-center items-center">
{LoadingSpinner}
</div>
)}
>
<option value="true">True</option>
<option value="false">False</option>
</select>
<button
type="submit"
className="w-full bg-[#495FA9] text-white py-2 px-4 rounded-lg hover:bg-[#475299]"
>
{isPending ? "Processing..." : "Register"}
</button>
</form>
{isPending && !isSuccess && (
<div className="mt-4 text-center text-gray-700">
Please sign the transaction with your wallet.
</div>
)}
{isSuccess && isConfirming && (
<div className="mt-4 text-center text-gray-700">
Waiting for confirmation...
{isPending && (
<div className="flex justify-center items-center mt-4">
{LoadingSpinner}
</div>
)}
{isConfirmed && (
{isSuccess && (
<div className="mt-4 text-center text-green-600">
Transaction confirmed. You will be redirected to your dashboard.
<p>
View on Etherscan:
<a
href={`https://etherscan.io/tx/`}
rel="noreferrer"
target="_blank"
className="text-blue-500 hover:underline"
>
Transaction Link
</a>
</p>
<p>
Go to your{" "}
<a href="/dashboard" className="text-blue-500 hover:underline">
dashboard
</a>
.
</p>
</div>
)}
{isError && (
<div className="mt-4 text-center text-red-600">
Error submitting transaction.
</div>
)}
</div>
);
};

export default RegisterSchemaForm;
Loading

0 comments on commit 4b54855

Please sign in to comment.