mirror of
https://github.com/Sosokker/B2D-Ventures.git
synced 2025-12-18 13:34:06 +01:00
feat: add legal-related page
This commit is contained in:
parent
e1b6ba450c
commit
0d937e10ba
44
src/app/(legal)/NavigationSidebar.tsx
Normal file
44
src/app/(legal)/NavigationSidebar.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
"use client";
|
||||
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import Link from "next/link";
|
||||
|
||||
export function NavSidebar() {
|
||||
return (
|
||||
<div className="w-64 p-6 bg-gray-100 dark:bg-gray-800 text-white shadow-lg rounded-lg border-2 border-gray-300 dark:border-gray-600">
|
||||
<ul className="space-y-4 sticky top-24 text-black dark:text-white">
|
||||
<Link href="/about">
|
||||
<li className="flex items-center p-2 relative group hover:scale-105 transition-all duration-200 ease-in-out rounded-md">
|
||||
<span>About</span>
|
||||
<div className="absolute bottom-0 left-0 w-full h-[2px] bg-blue-600 scale-x-0 group-hover:scale-x-100 transition-all duration-300"></div>
|
||||
</li>
|
||||
</Link>
|
||||
<Separator className="bg-gray-200 dark:bg-gray-700" />
|
||||
|
||||
<Link href="/privacy">
|
||||
<li className="flex items-center p-2 relative group hover:scale-105 transition-all duration-200 ease-in-out rounded-md">
|
||||
<span>Privacy</span>
|
||||
<div className="absolute bottom-0 left-0 w-full h-[2px] bg-blue-600 scale-x-0 group-hover:scale-x-100 transition-all duration-300"></div>
|
||||
</li>
|
||||
</Link>
|
||||
<Separator className="bg-gray-200 dark:bg-gray-700" />
|
||||
|
||||
<Link href="/risks">
|
||||
<li className="flex items-center p-2 relative group hover:scale-105 transition-all duration-200 ease-in-out rounded-md">
|
||||
<span>Risks</span>
|
||||
<div className="absolute bottom-0 left-0 w-full h-[2px] bg-blue-600 scale-x-0 group-hover:scale-x-100 transition-all duration-300"></div>
|
||||
</li>
|
||||
</Link>
|
||||
<Separator className="bg-gray-200 dark:bg-gray-700" />
|
||||
|
||||
<Link href="/terms">
|
||||
<li className="flex items-center p-2 relative group hover:scale-105 transition-all duration-200 ease-in-out rounded-md">
|
||||
<span>Terms</span>
|
||||
<div className="absolute bottom-0 left-0 w-full h-[2px] bg-blue-600 scale-x-0 group-hover:scale-x-100 transition-all duration-300"></div>
|
||||
</li>
|
||||
</Link>
|
||||
<Separator className="bg-gray-200 dark:bg-gray-700" />
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
31
src/app/(legal)/Toc.tsx
Normal file
31
src/app/(legal)/Toc.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
|
||||
interface Section {
|
||||
id: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface TableOfContentProps {
|
||||
sections: Section[];
|
||||
}
|
||||
|
||||
const TableOfContent = ({ sections }: TableOfContentProps) => {
|
||||
return (
|
||||
<div className="w-64 p-6 bg-gray-100 dark:bg-gray-800 text-white shadow-lg rounded-lg border-border border-2">
|
||||
<h3 className="text-xl font-semibold text-blue-600 dark:text-blue-400 mb-6">Table of Contents</h3>
|
||||
<ul className="space-y-4 sticky top-24">
|
||||
{sections.map((section) => (
|
||||
<li key={section.id}>
|
||||
<Link href={`#${section.id}`} className="text-gray-800 dark:text-gray-300 hover:text-blue-400">
|
||||
{`${sections.indexOf(section) + 1}. ${section.title}`}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TableOfContent;
|
||||
101
src/app/(legal)/privacy/page.tsx
Normal file
101
src/app/(legal)/privacy/page.tsx
Normal file
@ -0,0 +1,101 @@
|
||||
"use client";
|
||||
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import TableOfContent from "../Toc";
|
||||
import { NavSidebar } from "../NavigationSidebar";
|
||||
|
||||
const PrivacyPolicy = () => {
|
||||
const sections = [
|
||||
{ id: "introduction", title: "Introduction" },
|
||||
{ id: "data-collection", title: "Data Collection" },
|
||||
{ id: "data-usage", title: "Data Usage" },
|
||||
{ id: "data-sharing", title: "Data Sharing" },
|
||||
{ id: "data-security", title: "Data Security" },
|
||||
{ id: "user-rights", title: "User Rights" },
|
||||
{ id: "changes", title: "Changes to Privacy Policy" },
|
||||
{ id: "contact", title: "Contact Information" },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="container max-w-screen-xl flex mt-5">
|
||||
<div className="flex gap-2">
|
||||
<NavSidebar />
|
||||
<TableOfContent sections={sections} />
|
||||
</div>
|
||||
|
||||
<div className="flex-1 ml-4">
|
||||
<Card className="w-full max-w-3xl bg-white dark:bg-gray-800 shadow-lg rounded-lg">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-3xl text-blue-600 dark:text-blue-400">Privacy Policy</CardTitle>
|
||||
<CardDescription className="text-sm text-gray-500 dark:text-gray-400">
|
||||
Last Updated: November 17, 2024
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="prose dark:prose-invert text-gray-800 dark:text-gray-200">
|
||||
<p>
|
||||
This Privacy Policy ("Policy") describes how we collect, use, and share your personal
|
||||
information when you access and use our Website.
|
||||
</p>
|
||||
|
||||
<h2 id="introduction">1. Introduction</h2>
|
||||
<p>
|
||||
We value your privacy. This Policy explains how we collect, use, and protect your personal data when you
|
||||
use our services.
|
||||
</p>
|
||||
|
||||
<h2 id="data-collection">2. Data Collection</h2>
|
||||
<p>
|
||||
We collect various types of information when you use our Website, including personal information,
|
||||
technical data, and usage data. This includes your name, email address, IP address, and device
|
||||
information.
|
||||
</p>
|
||||
|
||||
<h2 id="data-usage">3. Data Usage</h2>
|
||||
<p>
|
||||
The data we collect is used to improve our services, personalize your experience, and ensure the
|
||||
functionality of our Website. We may also use your data for marketing purposes and to communicate with
|
||||
you.
|
||||
</p>
|
||||
|
||||
<h2 id="data-sharing">4. Data Sharing</h2>
|
||||
<p>
|
||||
We do not sell your personal data to third parties. However, we may share your data with trusted
|
||||
partners for the purpose of providing our services, complying with legal obligations, or protecting our
|
||||
rights.
|
||||
</p>
|
||||
|
||||
<h2 id="data-security">5. Data Security</h2>
|
||||
<p>
|
||||
We take reasonable measures to secure your personal data and protect it from unauthorized access,
|
||||
alteration, disclosure, or destruction. However, no data transmission over the Internet can be
|
||||
guaranteed as 100% secure.
|
||||
</p>
|
||||
|
||||
<h2 id="user-rights">6. User Rights</h2>
|
||||
<p>
|
||||
You have the right to access, update, or delete your personal information. You may also object to the
|
||||
processing of your data or request a restriction on how we process your data.
|
||||
</p>
|
||||
|
||||
<h2 id="changes">7. Changes to Privacy Policy</h2>
|
||||
<p>
|
||||
We may update this Privacy Policy from time to time. Any changes will be posted on this page, and the
|
||||
updated date will be reflected at the top of the page. We encourage you to review this Policy regularly.
|
||||
</p>
|
||||
|
||||
<h2 id="contact">8. Contact Information</h2>
|
||||
<p>
|
||||
If you have any questions about this Privacy Policy or wish to exercise your rights, please contact us
|
||||
at privacy@b2dventure.com.
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex justify-center"></CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PrivacyPolicy;
|
||||
105
src/app/(legal)/risks/page.tsx
Normal file
105
src/app/(legal)/risks/page.tsx
Normal file
@ -0,0 +1,105 @@
|
||||
"use client";
|
||||
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import TableOfContent from "../Toc";
|
||||
import { NavSidebar } from "../NavigationSidebar";
|
||||
|
||||
const InvestmentRisks = () => {
|
||||
const sections = [
|
||||
{ id: "investment-risk", title: "Investment Risk" },
|
||||
{ id: "business-closure", title: "Business Closure" },
|
||||
{ id: "no-return", title: "No Return on Investment" },
|
||||
{ id: "market-conditions", title: "Market Conditions" },
|
||||
{ id: "regulatory-risk", title: "Regulatory Risk" },
|
||||
{ id: "liquidity-risk", title: "Liquidity Risk" },
|
||||
{ id: "economic-factors", title: "Economic Factors" },
|
||||
{ id: "mitigation-strategies", title: "Mitigation Strategies" },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="container max-w-screen-xl flex mt-5">
|
||||
<div className="flex gap-2">
|
||||
<NavSidebar />
|
||||
<TableOfContent sections={sections} />
|
||||
</div>
|
||||
|
||||
<div className="flex-1 ml-4">
|
||||
<Card className="w-full max-w-3xl bg-white dark:bg-gray-800 shadow-lg rounded-lg">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-3xl text-blue-600 dark:text-blue-400">Investment Risks</CardTitle>
|
||||
<CardDescription className="text-sm text-gray-500 dark:text-gray-400">
|
||||
Last Updated: November 17, 2024
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="prose dark:prose-invert text-gray-800 dark:text-gray-200">
|
||||
<p>
|
||||
Investing in opportunities through our platform carries inherent risks. It is important that you fully
|
||||
understand these risks before proceeding with any investment. This page outlines some of the potential
|
||||
risks associated with investing in businesses listed on our platform.
|
||||
</p>
|
||||
|
||||
<h2 id="investment-risk">1. Investment Risk</h2>
|
||||
<p>
|
||||
All investments carry risk. The value of your investment may fluctuate, and there is a possibility that
|
||||
you could lose the entire amount invested. You should only invest money that you can afford to lose.
|
||||
</p>
|
||||
|
||||
<h2 id="business-closure">2. Business Closure</h2>
|
||||
<p>
|
||||
The businesses listed on our platform may face financial difficulties or other challenges that could
|
||||
lead to their closure. In the event of a business closing, investors may lose their entire investment,
|
||||
and there may be no recourse for recovering the invested funds.
|
||||
</p>
|
||||
|
||||
<h2 id="no-return">3. No Return on Investment</h2>
|
||||
<p>
|
||||
While some businesses may generate returns, there is no guarantee that you will receive a return on your
|
||||
investment. If a business does not succeed or fails to generate profits, you may not receive any return
|
||||
on your investment.
|
||||
</p>
|
||||
|
||||
<h2 id="market-conditions">4. Market Conditions</h2>
|
||||
<p>
|
||||
Economic and market conditions can affect the success of a business. Factors such as changes in demand,
|
||||
competition, or overall market downturns can negatively impact the business’s ability to generate
|
||||
revenue and, consequently, affect your investment return.
|
||||
</p>
|
||||
|
||||
<h2 id="regulatory-risk">5. Regulatory Risk</h2>
|
||||
<p>
|
||||
Changes in laws or regulations could affect the operations of a business and impact its ability to
|
||||
operate successfully. Businesses may face additional compliance costs or regulatory restrictions, which
|
||||
can negatively impact their profitability and the value of your investment.
|
||||
</p>
|
||||
|
||||
<h2 id="liquidity-risk">6. Liquidity Risk</h2>
|
||||
<p>
|
||||
Investment opportunities on our platform may lack liquidity. This means you may not be able to easily
|
||||
sell or exit your investment when you wish. The inability to quickly liquidate an investment may impact
|
||||
your ability to access your funds.
|
||||
</p>
|
||||
|
||||
<h2 id="economic-factors">7. Economic Factors</h2>
|
||||
<p>
|
||||
Broader economic factors, such as inflation, unemployment, and interest rates, can influence business
|
||||
performance and impact your investment. Negative economic shifts can lead to a decline in investment
|
||||
value.
|
||||
</p>
|
||||
|
||||
<h2 id="mitigation-strategies">8. Mitigation Strategies</h2>
|
||||
<p>
|
||||
While we cannot eliminate all risks, we recommend conducting thorough due diligence before investing.
|
||||
Additionally, diversifying your investment portfolio and staying informed about market trends and
|
||||
business performance can help mitigate some of these risks.
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex justify-center"></CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvestmentRisks;
|
||||
108
src/app/(legal)/terms/page.tsx
Normal file
108
src/app/(legal)/terms/page.tsx
Normal file
@ -0,0 +1,108 @@
|
||||
"use client";
|
||||
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import TableOfContent from "../Toc";
|
||||
import { NavSidebar } from "../NavigationSidebar";
|
||||
|
||||
const TermsOfService = () => {
|
||||
const sections = [
|
||||
{ id: "eligibility", title: "Eligibility" },
|
||||
{ id: "user-accounts", title: "User Accounts" },
|
||||
{ id: "user-content", title: "User Content" },
|
||||
{ id: "investment-activity", title: "Investment Activity" },
|
||||
{ id: "disclaimers", title: "Disclaimers" },
|
||||
{ id: "limitation-of-liability", title: "Limitation of Liability" },
|
||||
{ id: "indemnification", title: "Indemnification" },
|
||||
{ id: "termination", title: "Termination" },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="container max-w-screen-xl flex mt-5">
|
||||
<div className="flex gap-2">
|
||||
<NavSidebar />
|
||||
<TableOfContent sections={sections} />
|
||||
</div>
|
||||
|
||||
<div className="flex-1 ml-4">
|
||||
<Card className="w-full max-w-3xl bg-white dark:bg-gray-800 shadow-lg rounded-lg">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-3xl text-blue-600 dark:text-blue-400">Terms of Service</CardTitle>
|
||||
<CardDescription className="text-sm text-gray-500 dark:text-gray-400">
|
||||
Last Updated: November 17, 2024
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="prose dark:prose-invert text-gray-800 dark:text-gray-200">
|
||||
<p>
|
||||
These Terms of Service ("Terms") govern your access to and use of the Website, which is owned
|
||||
and operated by B2DVenture Company LLC ("B2DVenture", "we", "us", or
|
||||
"our").
|
||||
</p>
|
||||
|
||||
<h2 id="eligibility">1. Eligibility</h2>
|
||||
<p>
|
||||
You must be at least 18 years old and have the legal capacity to enter into a binding agreement in order
|
||||
to use the Website. You may not access or use the Website if you are not qualified.
|
||||
</p>
|
||||
|
||||
<h2 id="user-accounts">2. User Accounts</h2>
|
||||
<p>
|
||||
In order to access certain features of the Website, such as uploading investment opportunities or making
|
||||
investments, you may be required to create an account.
|
||||
</p>
|
||||
<p>
|
||||
You are responsible for maintaining the confidentiality of your account information, including your
|
||||
username and password. You are also responsible for all activity that occurs under your account.
|
||||
</p>
|
||||
|
||||
<h2 id="user-content">3. User Content</h2>
|
||||
<p>
|
||||
The Website allows users to upload content, including images, videos, and text (collectively, "User
|
||||
Content"). You retain all ownership rights in your User Content. However, by uploading User Content
|
||||
to the Website, you grant B2DVenture a non-exclusive, royalty-free, worldwide license to use, reproduce,
|
||||
modify, publish, and distribute your User Content in connection with the Website and our business.
|
||||
</p>
|
||||
|
||||
<h2 id="investment-activity">4. Investment Activity</h2>
|
||||
<p>
|
||||
The Website is a platform that connects businesses seeking funding (the "Issuers") with
|
||||
potential investors (the "Investors"). B2DVenture does not act as a financial advisor, broker,
|
||||
or dealer. We do not recommend or endorse any particular investment opportunity.
|
||||
</p>
|
||||
|
||||
<h2 id="disclaimers">5. Disclaimers</h2>
|
||||
<p>
|
||||
The Website and the information contained herein are provided for informational purposes only and should
|
||||
not be considered as investment advice.
|
||||
</p>
|
||||
|
||||
<h2 id="limitation-of-liability">6. Limitation of Liability</h2>
|
||||
<p>
|
||||
B2DVenture shall not be liable for any damages arising out of or in connection with your use of the
|
||||
Website, including but not limited to, direct, indirect, incidental, consequential, or punitive damages.
|
||||
</p>
|
||||
|
||||
<h2 id="indemnification">7. Indemnification</h2>
|
||||
<p>
|
||||
You agree to indemnify and hold harmless B2DVenture, its officers, directors, employees, agents, and
|
||||
licensors from and against any and all claims, demands, losses, liabilities, costs, or expenses
|
||||
(including attorneys" fees) arising out of or in connection with your use of the Website or your
|
||||
violation of these Terms.
|
||||
</p>
|
||||
|
||||
<h2 id="termination">8. Termination</h2>
|
||||
<p>
|
||||
We may terminate your access to the Website for any reason, at any time, without notice. This includes
|
||||
if you violate any of these Terms, or if we believe that your use of the Website is harmful to us or to
|
||||
any other user.
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex justify-center"></CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TermsOfService;
|
||||
@ -3,6 +3,8 @@ import { Card, CardContent, CardFooter, CardDescription, CardHeader, CardTitle }
|
||||
import { LoginButton } from "@/components/auth/loginButton";
|
||||
import { LoginForm } from "@/components/auth/loginForm";
|
||||
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Login() {
|
||||
return (
|
||||
<div
|
||||
@ -23,7 +25,17 @@ export default function Login() {
|
||||
<LoginButton />
|
||||
</CardContent>
|
||||
<CardFooter className="text-xs justify-center">
|
||||
By signing up, you agree to the Terms of Service and acknowledge you’ve read our Privacy Policy.
|
||||
<span>
|
||||
By signing in, you agree to the{" "}
|
||||
<Link href="/terms" rel="noopener noreferrer" target="_blank" className="text-blue-600 underline">
|
||||
Terms of Service
|
||||
</Link>{" "}
|
||||
and acknowledge you’ve read our{" "}
|
||||
<Link href="/privacy" rel="noopener noreferrer" target="_blank" className="text-blue-600 underline">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
.
|
||||
</span>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
@ -3,11 +3,13 @@ import { Card, CardContent, CardFooter, CardDescription, CardHeader, CardTitle }
|
||||
import { SignupButton } from "@/components/auth/signupButton";
|
||||
import { SignupForm } from "@/components/auth/signupForm";
|
||||
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Signup() {
|
||||
return (
|
||||
<div
|
||||
className="bg-cover bg-center min-h-screen flex items-center justify-center"
|
||||
style={{ backgroundImage: "url(/signup.png)" }}
|
||||
style={{ backgroundImage: "url(/login.png)" }}
|
||||
>
|
||||
<Card>
|
||||
<CardHeader className="items-center">
|
||||
@ -23,7 +25,17 @@ export default function Signup() {
|
||||
<SignupButton />
|
||||
</CardContent>
|
||||
<CardFooter className="text-xs justify-center">
|
||||
By signing up, you agree to the Terms of Service and acknowledge you’ve read our Privacy Policy.
|
||||
<span>
|
||||
By signing up, you agree to the{" "}
|
||||
<Link href="/terms" rel="noopener noreferrer" target="_blank" className="text-blue-600 underline">
|
||||
Terms of Service
|
||||
</Link>{" "}
|
||||
and acknowledge you’ve read our{" "}
|
||||
<Link href="/privacy" rel="noopener noreferrer" target="_blank" className="text-blue-600 underline">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
.
|
||||
</span>{" "}
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
@ -18,13 +18,13 @@ export function SiteFooter() {
|
||||
<Link href="/about" className="hover:underline">
|
||||
About Us
|
||||
</Link>
|
||||
<Link href="/services" className="hover:underline">
|
||||
Services
|
||||
<Link href="/privacy" className="hover:underline">
|
||||
Privacy
|
||||
</Link>
|
||||
<Link
|
||||
href="mailto:b2d.ventures.contact@gmail.com"
|
||||
className="hover:underline"
|
||||
>
|
||||
<Link href="/terms" className="hover:underline">
|
||||
Terms and Service
|
||||
</Link>
|
||||
<Link href="mailto:b2d.ventures.contact@gmail.com" className="hover:underline">
|
||||
Contact
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
140
src/components/ui/sheet.tsx
Normal file
140
src/components/ui/sheet.tsx
Normal file
@ -0,0 +1,140 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as SheetPrimitive from "@radix-ui/react-dialog"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { X } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Sheet = SheetPrimitive.Root
|
||||
|
||||
const SheetTrigger = SheetPrimitive.Trigger
|
||||
|
||||
const SheetClose = SheetPrimitive.Close
|
||||
|
||||
const SheetPortal = SheetPrimitive.Portal
|
||||
|
||||
const SheetOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Overlay
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
/>
|
||||
))
|
||||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
|
||||
|
||||
const sheetVariants = cva(
|
||||
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
|
||||
{
|
||||
variants: {
|
||||
side: {
|
||||
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
||||
bottom:
|
||||
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
||||
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
||||
right:
|
||||
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
side: "right",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
interface SheetContentProps
|
||||
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
||||
VariantProps<typeof sheetVariants> {}
|
||||
|
||||
const SheetContent = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Content>,
|
||||
SheetContentProps
|
||||
>(({ side = "right", className, children, ...props }, ref) => (
|
||||
<SheetPortal>
|
||||
<SheetOverlay />
|
||||
<SheetPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(sheetVariants({ side }), className)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
||||
<X className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</SheetPrimitive.Close>
|
||||
</SheetPrimitive.Content>
|
||||
</SheetPortal>
|
||||
))
|
||||
SheetContent.displayName = SheetPrimitive.Content.displayName
|
||||
|
||||
const SheetHeader = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-2 text-center sm:text-left",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
SheetHeader.displayName = "SheetHeader"
|
||||
|
||||
const SheetFooter = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
SheetFooter.displayName = "SheetFooter"
|
||||
|
||||
const SheetTitle = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn("text-lg font-semibold text-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
SheetTitle.displayName = SheetPrimitive.Title.displayName
|
||||
|
||||
const SheetDescription = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Description>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
SheetDescription.displayName = SheetPrimitive.Description.displayName
|
||||
|
||||
export {
|
||||
Sheet,
|
||||
SheetPortal,
|
||||
SheetOverlay,
|
||||
SheetTrigger,
|
||||
SheetClose,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetFooter,
|
||||
SheetTitle,
|
||||
SheetDescription,
|
||||
}
|
||||
19
src/hooks/use-mobile.tsx
Normal file
19
src/hooks/use-mobile.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import * as React from "react"
|
||||
|
||||
const MOBILE_BREAKPOINT = 768
|
||||
|
||||
export function useIsMobile() {
|
||||
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
|
||||
|
||||
React.useEffect(() => {
|
||||
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
||||
const onChange = () => {
|
||||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
||||
}
|
||||
mql.addEventListener("change", onChange)
|
||||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
||||
return () => mql.removeEventListener("change", onChange)
|
||||
}, [])
|
||||
|
||||
return !!isMobile
|
||||
}
|
||||
@ -14,6 +14,6 @@ export const config = {
|
||||
* - favicon.ico (favicon file)
|
||||
* Feel free to modify this pattern to include more paths.
|
||||
*/
|
||||
"/((?!_next/static|_next/image|$|favicon.ico|payment-success|verify|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
|
||||
"/((?!_next/static|_next/image|$|favicon.ico|payment-success|verify|terms|contact|risks|about|privacy|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
|
||||
],
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user