Skip to content

Commit

Permalink
feat(#212): implemented user profile with grid
Browse files Browse the repository at this point in the history
  • Loading branch information
sametcodes committed May 15, 2024
1 parent 530744a commit b27dfe5
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 0 deletions.
77 changes: 77 additions & 0 deletions app/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// "use client";

import prisma from "@/services/prisma";
import { Platform, PlatformCode, PlatformQuery } from "@prisma/client";
import { templates, samples } from "@/platforms";
import { RocksGridBuilder } from "@/components/widget/builder";

type IPlatformQueries = {
platform: Platform & { queries: Array<PlatformQuery> };
};

const PlatformQueries = async ({ platform }: IPlatformQueries, key: string) => {
const template = templates[platform.code];
const sample = samples[platform.code];

return Promise.all(
platform.queries.map((query) =>
PlatformQueryView(
{
query,
template: template as any,
sample: sample as any,
},
query.id
)
)
);
};

type IPlatformQueryView = {
query: PlatformQuery;
template: {
[key in keyof typeof PlatformCode]: (
...params: any
) => Promise<JSX.Element>;
};
sample: { [key in keyof typeof PlatformCode]: any };
};

const PlatformQueryView = async (
{ query, template, sample }: IPlatformQueryView,
key: string
) => {
const getView = template[query.name as keyof typeof template];
const sampleData = sample[query.name as keyof typeof samples];
if (!sampleData) return <>No data.</>;

return getView(sampleData.result, sampleData.config);
};

type UserOwnProfileProps = { params: { uid: string } };
export default async function UserOwnProfile({ params }: UserOwnProfileProps) {
const platforms = await prisma.platform.findMany({
include: {
queries: {
where: { publicQueryId: { isSet: false } },
},
},
});

const rocksWithView = (
await Promise.all(
platforms.map((platform) => PlatformQueries({ platform }, platform.id))
)
).flatMap((item) => item);

return (
<div className="container mx-auto flex">
<div className="basis-1/4 w-16">
<p>User profile</p>
</div>
<div className="basis-3/4 w-32">
<RocksGridBuilder rocks={rocksWithView} />
</div>
</div>
);
}
29 changes: 29 additions & 0 deletions app/user/[uid]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Profile } from "@/components/layout/profile";
import { RocksGridBuilder } from "@/components/widget/builder";
import prisma from "@/services/prisma";

type UserProfileProps = {
params: {
uid: string;
};
};

export default async function UserProfile({ params }: UserProfileProps) {
const userId = params.uid;

const user = await prisma.user.findUnique({
where: { id: userId },
});
if (!user) return <p>User not found</p>;

return (
<div className="container mx-auto py-24 flex divide-y-2">
<div className="w-1/6">
<Profile user={user} />
</div>
<div className="w-5/2">
<RocksGridBuilder rocks={[]} />
</div>
</div>
);
}
4 changes: 4 additions & 0 deletions components/layout/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const links = [

export default function NavbarWithLogin({ session }: INavbarWithLogin) {
const segment = useSelectedLayoutSegment();

return (
<div className="flex h-16 mx-auto px-8 sm:px-0 items-center justify-between border-b border-b-slate-200 py-4 dark:border-b-gray-500">
<Link href="/" className="items-center space-x-2 md:flex">
Expand Down Expand Up @@ -82,6 +83,9 @@ export default function NavbarWithLogin({ session }: INavbarWithLogin) {
<DropdownMenuItem>{link.title}</DropdownMenuItem>
</Link>
))}
<DropdownMenuItem className="text-slate-500">
<Link href="/profile">Profile</Link>
</DropdownMenuItem>
<DropdownMenuItem className="text-slate-500">
<Link href="/connect">Connects</Link>
</DropdownMenuItem>
Expand Down
23 changes: 23 additions & 0 deletions components/layout/profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { User } from "@prisma/client";
import NextImage from "next/image";

type ProfileType = {
user: User;
};

export const Profile = ({ user }: ProfileType) => {
return (
<div className="flex flex-col justify-center items-center py-3">
{user.image && (
<NextImage
className="rounded-full border-gray-300 border"
alt={user.name || ""}
src={user.image}
width={200}
height={200}
/>
)}
<p className="text-3xl py-4">{user.name}</p>
</div>
);
};
2 changes: 2 additions & 0 deletions components/ui/image.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import { useState } from "react";
import NextImage, { ImageProps } from "next/image";
import { cn } from "@/utils";
Expand Down
71 changes: 71 additions & 0 deletions components/widget/builder.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"use client";

import { Responsive, WidthProvider } from "react-grid-layout";
import "react-grid-layout/css/styles.css";
import "react-resizable/css/styles.css";
import { useMemo } from "react";
import { FaPlus } from "react-icons/fa";

const ResponsiveGridLayout = WidthProvider(Responsive);

type RocksGridBuilderProps = {
rocks: Array<JSX.Element>;
};

export function RocksGridBuilder({ rocks }: RocksGridBuilderProps) {
// const layout: Array<Layout> = [];

function onBreakpointChange(newBreakpoint: string, newCols: number) {
console.log({ newBreakpoint, newCols });
}

const addPlaceholder = useMemo(
() => (
<div
key={"grid_0"}
data-grid={{
x: 0,
y: 0,
w: 1,
h: 1,
isResizable: false,
}}
>
<div className="flex flex-col justify-center items-center text-center border-gray-300 border">
<FaPlus className="text-2xl" color="#555555" fontWeight="300" />
<p>Add a widget</p>
</div>
</div>
),
[]
);

return (
<ResponsiveGridLayout
className="layout"
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
onBreakpointChange={onBreakpointChange}
rowHeight={30}
autoSize={true}
>
{addPlaceholder}
{rocks.map((rock, index) => {
return (
<div
key={index}
data-grid={{
x: 0,
y: 0,
w: rock.props.width / 30 / 4,
h: rock.props.height / 30,
isResizable: false,
}}
>
{rock}
</div>
);
})}
</ResponsiveGridLayout>
);
}
57 changes: 57 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"qs": "^6.11.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-grid-layout": "^1.3.4",
"react-icons": "^4.8.0",
"tailwind-merge": "^1.10.0",
"yup": "^1.0.2"
Expand All @@ -63,6 +64,7 @@
"@types/passport-oauth2-refresh": "^1.1.1",
"@types/react": "^18.3.2",
"@types/react-dom": "18.0.8",
"@types/react-grid-layout": "^1.3.2",
"@types/testing-library__jest-dom": "^5.14.5",
"autoprefixer": "^10.4.14",
"copy-webpack-plugin": "^11.0.0",
Expand Down

0 comments on commit b27dfe5

Please sign in to comment.