diff --git a/apps/frontend/src/app/(site)/marketplace/buyer/page.tsx b/apps/frontend/src/app/(site)/marketplace/buyer/page.tsx
new file mode 100644
index 00000000..3f09e89b
--- /dev/null
+++ b/apps/frontend/src/app/(site)/marketplace/buyer/page.tsx
@@ -0,0 +1,16 @@
+import { Buyer } from '@gitroom/frontend/components/marketplace/buyer';
+
+export const dynamic = 'force-dynamic';
+import { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: 'Gitroom Marketplace',
+ description: '',
+};
+export default async function Index({
+ searchParams,
+}: {
+ searchParams: { code: string };
+}) {
+ return ;
+}
diff --git a/apps/frontend/src/app/(site)/marketplace/layout.tsx b/apps/frontend/src/app/(site)/marketplace/layout.tsx
new file mode 100644
index 00000000..9589be86
--- /dev/null
+++ b/apps/frontend/src/app/(site)/marketplace/layout.tsx
@@ -0,0 +1,11 @@
+import { BuyerSeller } from '@gitroom/frontend/components/marketplace/buyer.seller';
+import { ReactNode } from 'react';
+
+export default function Layout({ children }: { children: ReactNode }) {
+ return (
+ <>
+
+ {children}
+ >
+ )
+}
\ No newline at end of file
diff --git a/apps/frontend/src/app/(site)/marketplace/page.tsx b/apps/frontend/src/app/(site)/marketplace/page.tsx
new file mode 100644
index 00000000..665b9cd4
--- /dev/null
+++ b/apps/frontend/src/app/(site)/marketplace/page.tsx
@@ -0,0 +1,17 @@
+export const dynamic = 'force-dynamic';
+import { Metadata } from 'next';
+import { cookies } from 'next/headers';
+import { redirect } from 'next/navigation';
+
+export const metadata: Metadata = {
+ title: 'Gitroom Marketplace',
+ description: '',
+};
+export default async function Index({
+ searchParams,
+}: {
+ searchParams: { code: string };
+}) {
+ const currentCookie = cookies()?.get('marketplace')?.value;
+ return redirect(currentCookie === 'buyer' ? '/marketplace/buyer' : '/marketplace/seller');
+}
diff --git a/apps/frontend/src/app/(site)/marketplace/seller/page.tsx b/apps/frontend/src/app/(site)/marketplace/seller/page.tsx
new file mode 100644
index 00000000..c9377f6a
--- /dev/null
+++ b/apps/frontend/src/app/(site)/marketplace/seller/page.tsx
@@ -0,0 +1,16 @@
+import { Seller } from '@gitroom/frontend/components/marketplace/seller';
+
+export const dynamic = 'force-dynamic';
+import { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: 'Gitroom Marketplace',
+ description: '',
+};
+export default async function Index({
+ searchParams,
+}: {
+ searchParams: { code: string };
+}) {
+ return ;
+}
diff --git a/apps/frontend/src/components/layout/title.tsx b/apps/frontend/src/components/layout/title.tsx
index 2cf2aaa3..5e0b0aa3 100644
--- a/apps/frontend/src/components/layout/title.tsx
+++ b/apps/frontend/src/components/layout/title.tsx
@@ -7,7 +7,7 @@ import {menuItems} from "@gitroom/frontend/components/layout/top.menu";
export const Title = () => {
const path = usePathname();
const currentTitle = useMemo(() => {
- return menuItems.find(item => item.path === path)?.name;
+ return menuItems.find(item => path.indexOf(item.path) > -1)?.name;
}, [path]);
return (
diff --git a/apps/frontend/src/components/layout/top.menu.tsx b/apps/frontend/src/components/layout/top.menu.tsx
index f9ee9f2a..ba9a0780 100644
--- a/apps/frontend/src/components/layout/top.menu.tsx
+++ b/apps/frontend/src/components/layout/top.menu.tsx
@@ -29,6 +29,11 @@ export const menuItems = [
path: '/billing',
role: ['ADMIN', 'SUPERADMIN'],
},
+ {
+ name: 'Marketplace',
+ icon: 'marketplace',
+ path: '/marketplace',
+ },
];
export const TopMenu: FC = () => {
@@ -59,8 +64,8 @@ export const TopMenu: FC = () => {
}
return true;
})
- .map((p) => p.path)
- .indexOf(path) === index
+ .map((p) => path.indexOf(p.path) > -1 ? index : -1)
+ .indexOf(index) === index
? 'text-primary showbox'
: 'text-gray'
)}
diff --git a/apps/frontend/src/components/marketplace/buyer.seller.tsx b/apps/frontend/src/components/marketplace/buyer.seller.tsx
new file mode 100644
index 00000000..7562693b
--- /dev/null
+++ b/apps/frontend/src/components/marketplace/buyer.seller.tsx
@@ -0,0 +1,20 @@
+"use client";
+import { FC } from 'react';
+import { usePathname } from 'next/navigation';
+import clsx from 'clsx';
+import Link from 'next/link';
+
+export const BuyerSeller: FC = () => {
+ const path = usePathname();
+ const pathComputed = path === '/marketplace' ? '/marketplace/seller' : path;
+ return (
+
+
+
+ -1 && 'bg-forth')}>Seller
+ -1 && 'bg-forth')}>Buyer
+
+
+
+ );
+};
diff --git a/apps/frontend/src/components/marketplace/buyer.tsx b/apps/frontend/src/components/marketplace/buyer.tsx
new file mode 100644
index 00000000..3e407592
--- /dev/null
+++ b/apps/frontend/src/components/marketplace/buyer.tsx
@@ -0,0 +1,235 @@
+'use client';
+
+import { FC, useCallback, useRef, useState } from 'react';
+import { Checkbox } from '@gitroom/react/form/checkbox';
+import { useRouter, useSearchParams } from 'next/navigation';
+import clsx from 'clsx';
+import interClass from '@gitroom/react/helpers/inter.font';
+import { Button } from '@gitroom/react/form/button';
+
+export const LabelCheckbox: FC<{
+ label: string;
+ name: string;
+ value: string;
+ checked: boolean;
+ onChange: (value: string, status: boolean) => void;
+}> = (props) => {
+ const { label, name, value, checked, onChange } = props;
+ const ref = useRef(null);
+ const [innerCheck, setInnerCheck] = useState(checked);
+
+ const change = useCallback(() => {
+ setInnerCheck(!innerCheck);
+ onChange(value, !innerCheck);
+ }, [innerCheck]);
+
+ return (
+
+
+
+
+ );
+};
+
+export const Options: FC<{
+ title: string;
+ options: Array<{ key: string; value: string }>;
+ query: string;
+}> = (props) => {
+ const { title, options, query } = props;
+ const router = useRouter();
+ const searchParams = (useSearchParams().get(query) || '')?.split(',') || [];
+
+ const change = (value: string, state: boolean) => {
+ const getAll = new URLSearchParams(window.location.search).get(query);
+ const splitAll = (getAll?.split(',') || []).filter((f) => f);
+
+ if (state) {
+ splitAll?.push(value);
+ } else {
+ splitAll?.splice(splitAll.indexOf(value), 1);
+ }
+
+ const params = new URLSearchParams(window.location.search);
+ if (!splitAll?.length) {
+ params.delete(query);
+ } else {
+ params.set(query, splitAll?.join(',') || '');
+ }
+
+ router.replace('?' + params.toString());
+ return params.toString();
+ };
+
+ return (
+ <>
+
+ {title}
+
+
+ {options.map((option) => (
+
+ -1}
+ name={query}
+ onChange={change}
+ />
+
+ ))}
+
+ >
+ );
+};
+
+export const Card = () => {
+ return (
+
+
+
+
+

+
+
+
+
+
+
Nevo David
+
+
+ Content Writer
+
+
+ Influencer
+
+
+
+
+
+ Maecenas dignissim justo eget nulla rutrum molestie. Maecenas
+ lobortis sem dui,
+
+
+
+
+
+
+
+
+ );
+};
+
+export const Buyer = () => {
+ return (
+
+
+
+
234 Result
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/apps/frontend/src/components/marketplace/marketplace.tsx b/apps/frontend/src/components/marketplace/marketplace.tsx
new file mode 100644
index 00000000..46e033b4
--- /dev/null
+++ b/apps/frontend/src/components/marketplace/marketplace.tsx
@@ -0,0 +1,3 @@
+export const Marketplace = () => {
+ return
+}
\ No newline at end of file
diff --git a/apps/frontend/src/components/marketplace/seller.tsx b/apps/frontend/src/components/marketplace/seller.tsx
new file mode 100644
index 00000000..6945d321
--- /dev/null
+++ b/apps/frontend/src/components/marketplace/seller.tsx
@@ -0,0 +1,32 @@
+'use client';
+
+import { Slider } from "@gitroom/react/form/slider";
+import { Button } from '@gitroom/react/form/button';
+
+export const Seller = () => {
+ return (
+
+
+
Seller Mode
+
+
+
John Smith
+
+
+
+
+
+
+
+
+
Details
+
+ asdfasdf
+
+
+
+ );
+};
diff --git a/apps/frontend/src/middleware.ts b/apps/frontend/src/middleware.ts
index 027d1d5e..021f0529 100644
--- a/apps/frontend/src/middleware.ts
+++ b/apps/frontend/src/middleware.ts
@@ -90,7 +90,26 @@ export async function middleware(request: NextRequest) {
return NextResponse.redirect(new URL(`/analytics`, nextUrl.href));
}
- return NextResponse.next();
+ const next = NextResponse.next();
+
+ if (
+ nextUrl.pathname === '/marketplace/seller' ||
+ nextUrl.pathname === '/marketplace/buyer'
+ ) {
+ const type = nextUrl.pathname.split('/marketplace/')[1].split('/')[0];
+
+ next.cookies.set('marketplace', type === 'seller' ? 'seller' : 'buyer', {
+ path: '/',
+ sameSite: false,
+ httpOnly: true,
+ secure: true,
+ expires: new Date(Date.now() + 15 * 60 * 1000),
+ domain:
+ '.' + new URL(removeSubdomain(process.env.FRONTEND_URL!)).hostname,
+ });
+ }
+
+ return next;
} catch (err) {
return NextResponse.redirect(new URL('/auth/logout', nextUrl.href));
}
diff --git a/libraries/nestjs-libraries/src/database/prisma/schema.prisma b/libraries/nestjs-libraries/src/database/prisma/schema.prisma
index e3c258e8..493ae4bd 100644
--- a/libraries/nestjs-libraries/src/database/prisma/schema.prisma
+++ b/libraries/nestjs-libraries/src/database/prisma/schema.prisma
@@ -32,6 +32,10 @@ model User {
email String
password String?
providerName Provider
+ name String?
+ lastName String?
+ pictureId String?
+ picture Media? @relation(fields: [pictureId], references: [id])
providerId String?
organizations UserOrganization[]
timezone Int
@@ -40,6 +44,7 @@ model User {
updatedAt DateTime @updatedAt
lastReadNotifications DateTime @default(now())
inviteId String?
+ tagUser TagUser[]
@@unique([email, providerName])
@@index([lastReadNotifications])
@@ -94,6 +99,21 @@ model TrendingLog {
date DateTime
}
+model TagUser {
+ id String @id @default(uuid())
+ user User @relation(fields: [userId], references: [id])
+ userId String
+ tagOptions TagOptions @relation(fields: [tagOptionsId], references: [id])
+ tagOptionsId String
+}
+
+model TagOptions {
+ id String @id @default(uuid())
+ key String
+ value String
+ tagUser TagUser[]
+}
+
model Star {
id String @id @default(uuid())
stars Int
@@ -116,6 +136,7 @@ model Media {
organizationId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
+ userPicture User[]
@@index([organizationId])
}
diff --git a/libraries/react-shared-libraries/src/form/checkbox.tsx b/libraries/react-shared-libraries/src/form/checkbox.tsx
index a335d39d..59ef4790 100644
--- a/libraries/react-shared-libraries/src/form/checkbox.tsx
+++ b/libraries/react-shared-libraries/src/form/checkbox.tsx
@@ -1,17 +1,18 @@
'use client';
-import { FC, useCallback, useState } from 'react';
+import { FC, forwardRef, useCallback, useState } from 'react';
import clsx from 'clsx';
import Image from 'next/image';
import { useFormContext, useWatch } from 'react-hook-form';
-export const Checkbox: FC<{
+export const Checkbox = forwardRef void;
-}> = (props) => {
- const { checked, className, disableForm } = props;
+ variant?: 'default' | 'hollow';
+}>((props, ref: any) => {
+ const { checked, className, disableForm, variant } = props;
const form = useFormContext();
const register = disableForm ? {} : form.register(props.name!);
@@ -31,10 +32,12 @@ export const Checkbox: FC<{
return (
@@ -43,4 +46,4 @@ export const Checkbox: FC<{
)}
);
-};
+});
diff --git a/libraries/react-shared-libraries/src/form/slider.tsx b/libraries/react-shared-libraries/src/form/slider.tsx
index 3e63fedb..0add647c 100644
--- a/libraries/react-shared-libraries/src/form/slider.tsx
+++ b/libraries/react-shared-libraries/src/form/slider.tsx
@@ -3,17 +3,17 @@
import {FC, useCallback} from "react";
import clsx from "clsx";
-export const Slider: FC<{value: 'on' | 'off', onChange: (value: 'on' | 'off') => void}> = (props) => {
- const {value, onChange} = props;
+export const Slider: FC<{value: 'on' | 'off', fill?: boolean, onChange: (value: 'on' | 'off') => void}> = (props) => {
+ const {value, onChange, fill} = props;
const change = useCallback(() => {
onChange(value === 'on' ? 'off' : 'on');
}, [value]);
return (
-
+
)
-}
\ No newline at end of file
+}