mirror of
https://github.com/wasp-lang/open-saas.git
synced 2025-11-19 01:56:45 +01:00
Move shadcn directories to client shared folder + update shadcn docs a bit (#551)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
--- template/app/README.md
|
||||
+++ opensaas-sh/app/README.md
|
||||
@@ -1,6 +1,8 @@
|
||||
@@ -1,12 +1,27 @@
|
||||
-# <YOUR_APP_NAME>
|
||||
+# opensaas.sh (demo) app
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
+
|
||||
+It is deployed to https://opensaas.sh and serves both as a landing page for Open Saas and as a demo app.
|
||||
|
||||
## UI Components
|
||||
|
||||
@@ -8,9 +10,22 @@
|
||||
|
||||
## Development
|
||||
|
||||
+### .env files
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
import { Link as ReactRouterLink } from "react-router-dom";
|
||||
import { useAuth } from "wasp/client/auth";
|
||||
import { Link as WaspRouterLink, routes } from "wasp/client/router";
|
||||
+import { Button } from "../../../components/ui/button";
|
||||
+import { Button } from "../../../client/components/ui/button";
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
@@ -17,6 +18,7 @@
|
||||
import { useIsLandingPage } from "../../hooks/useIsLandingPage";
|
||||
import logo from "../../static/logo.webp";
|
||||
import { cn } from "../../utils";
|
||||
import DarkModeSwitcher from "../DarkModeSwitcher";
|
||||
+import RepoInfo from "../RepoInfo";
|
||||
import { Announcement } from "./Announcement";
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
@@ -0,0 +1,48 @@
|
||||
+import { useEffect, useState } from "react";
|
||||
+import { FaGithub } from "react-icons/fa";
|
||||
+import { Button } from "../../components/ui/button";
|
||||
+import { formatNumber } from "../../lib/utils";
|
||||
+import { Button } from "../../client/components/ui/button";
|
||||
+import { formatNumber } from "../utils";
|
||||
+
|
||||
+const RepoInfo = () => {
|
||||
+ const [repoInfo, setRepoInfo] = useState<null | any>(null);
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
--- template/app/src/components/ui/button.tsx
|
||||
+++ opensaas-sh/app/src/components/ui/button.tsx
|
||||
@@ -5,26 +5,31 @@
|
||||
import { cn } from "../../lib/utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
{
|
||||
--- template/app/src/client/components/ui/button.tsx
|
||||
+++ opensaas-sh/app/src/client/components/ui/button.tsx
|
||||
@@ -10,21 +10,26 @@
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
@@ -1,5 +1,5 @@
|
||||
--- template/app/src/components/ui/card.tsx
|
||||
+++ opensaas-sh/app/src/components/ui/card.tsx
|
||||
--- template/app/src/client/components/ui/card.tsx
|
||||
+++ opensaas-sh/app/src/client/components/ui/card.tsx
|
||||
@@ -12,7 +12,11 @@
|
||||
accent: "bg-card-accent text-card-accent-foreground hover:scale-[1.02]",
|
||||
faded: "text-card-faded-foreground scale-95 opacity-50",
|
||||
@@ -1,5 +1,5 @@
|
||||
--- template/app/src/lib/utils.ts
|
||||
+++ opensaas-sh/app/src/lib/utils.ts
|
||||
--- template/app/src/client/utils.ts
|
||||
+++ opensaas-sh/app/src/client/utils.ts
|
||||
@@ -4,3 +4,12 @@
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
@@ -3,9 +3,9 @@
|
||||
@@ -0,0 +1,163 @@
|
||||
+import { useState } from "react";
|
||||
+import { FaDiscord, FaGithub, FaGoogle, FaSlack } from "react-icons/fa";
|
||||
+import { Button } from "../../../components/ui/button";
|
||||
+import { Card, CardContent, CardHeader } from "../../../components/ui/card";
|
||||
+import { Input } from "../../../components/ui/input";
|
||||
+import { Button } from "../../../client/components/ui/button";
|
||||
+import { Card, CardContent, CardHeader } from "../../../client/components/ui/card";
|
||||
+import { Input } from "../../../client/components/ui/input";
|
||||
+import { DocsUrl } from "../../../shared/common";
|
||||
+import HighlightedFeature from "../HighlightedFeature";
|
||||
+
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
+import { Link as ReactRouterLink } from "react-router-dom";
|
||||
+import { useAuth } from "wasp/client/auth";
|
||||
+import { Link as WaspRouterLink, routes } from "wasp/client/router";
|
||||
+import { Button } from "../../../components/ui/button";
|
||||
+import { Button } from "../../../client/components/ui/button";
|
||||
+import { DocsUrl, WaspUrl } from "../../../shared/common";
|
||||
+import Orbit from "./Orbit";
|
||||
+
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
+import stripeLogo from "../../../client/static/logos/stripe-light.webp";
|
||||
+import tailwindLogoDark from "../../../client/static/logos/tailwind-dark.webp";
|
||||
+import tailwindLogo from "../../../client/static/logos/tailwind-light.webp";
|
||||
+import { cn } from "../../../lib/utils";
|
||||
+import { cn } from "../../../client/utils";
|
||||
+import AstroLogo from "../../logos/AstroLogo";
|
||||
+import OpenAILogo from "../../logos/OpenAILogo";
|
||||
+import PrismaLogo from "../../logos/PrismaLogo";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- template/app/src/payment/paymentProcessor.ts
|
||||
+++ opensaas-sh/app/src/payment/paymentProcessor.ts
|
||||
@@ -28,9 +28,4 @@
|
||||
@@ -29,9 +29,4 @@
|
||||
webhookMiddlewareConfigFn: MiddlewareConfigFn;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- template/app/src/payment/stripe/user.ts
|
||||
+++ opensaas-sh/app/src/payment/stripe/user.ts
|
||||
@@ -3,7 +3,7 @@
|
||||
@@ -4,7 +4,7 @@
|
||||
import type { SubscriptionStatus } from "../plans";
|
||||
import { PaymentPlanId } from "../plans";
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
userId: User["id"],
|
||||
prismaUserDelegate: PrismaClient["user"],
|
||||
): Promise<string | null> {
|
||||
@@ -12,20 +12,20 @@
|
||||
@@ -13,20 +13,20 @@
|
||||
id: userId,
|
||||
},
|
||||
select: {
|
||||
@@ -36,7 +36,7 @@
|
||||
prismaUserDelegate: PrismaClient["user"],
|
||||
): Promise<User> {
|
||||
return prismaUserDelegate.update({
|
||||
@@ -33,7 +33,7 @@
|
||||
@@ -34,7 +34,7 @@
|
||||
id: userId,
|
||||
},
|
||||
data: {
|
||||
@@ -45,7 +45,7 @@
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -54,7 +54,7 @@
|
||||
@@ -55,7 +55,7 @@
|
||||
): Promise<User> {
|
||||
return userDelegate.update({
|
||||
where: {
|
||||
@@ -54,7 +54,7 @@
|
||||
},
|
||||
data: {
|
||||
datePaid,
|
||||
@@ -81,7 +81,7 @@
|
||||
@@ -82,7 +82,7 @@
|
||||
): Promise<User> {
|
||||
return userDelegate.update({
|
||||
where: {
|
||||
|
||||
@@ -2,40 +2,45 @@
|
||||
description: Describes where the ui components built on top with Shadcn UI exist, how they are customized, and Wasp specific rules concerning how new ShadCN UI components should be installed
|
||||
alwaysApply: false
|
||||
---
|
||||
Only ShadCN UI version 2.3.0 should be used with Wasp at the moment. Due to dependency conflicts Wasp cannot be used with Tailwindcss v4, which the newer version of Shadcn depends on.
|
||||
Due to dependency conflicts Wasp cannot be used with Tailwindcss v4.
|
||||
|
||||
Shadcn has already been setup with this project template, so there is no need to install it. All the ShadCN specific components exist in [src/components/ui](../../src/components/ui/)
|
||||
ShadCN has already been setup with this project template, so there is no need to install it. All the ShadCN specific components exist in [src/client/components/ui](../../src/client/components/ui/)
|
||||
|
||||
## Adding a new ShadCN component
|
||||
### 1. Add a new component
|
||||
|
||||
We will use button as an example.
|
||||
Same rules apply to any ShadCN component.
|
||||
|
||||
### 1. Add a new component
|
||||
|
||||
```bash
|
||||
npx shadcn@2.3.0 add button
|
||||
npx shadcn@latest add button
|
||||
```
|
||||
|
||||
### 2. Adjust the `utils` import in `button.tsx` (for each component you add)
|
||||
This will generate a button component in `src/client/components/ui/button.tsx`.
|
||||
|
||||
### 2. Adjust the `utils` import in `button.tsx`
|
||||
|
||||
There will be a brand new `button.tsx` file in `src/components/ui`. We need to fix some import issues:
|
||||
```diff
|
||||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
-import { cn } from "s/lib/utils"
|
||||
+import { cn } from "../../lib/utils"
|
||||
-import { cn } from "src/lib/utils"
|
||||
+import { cn } from "../../utils"
|
||||
```
|
||||
|
||||
### 3. Use the `Button` component
|
||||
Now you are ready to use the `Button` component. That's it!
|
||||
```jsx
|
||||
import './Main.css'
|
||||
### 3. Use the `Button` React component
|
||||
|
||||
Now you are ready to use the `Button` component. That's it!
|
||||
```tsx
|
||||
import { Button } from './components/ui/button'
|
||||
|
||||
export const MainPage = () => {
|
||||
function SomePage() {
|
||||
return (
|
||||
<div className="container">
|
||||
<div>
|
||||
<Button>This works</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
Built with [Wasp](https://wasp.sh), based on the [Open Saas](https://opensaas.sh) template.
|
||||
|
||||
## UI Components
|
||||
|
||||
This template includes [ShadCN UI](https://ui.shadcn.com/) v2 for beautiful, accessible React components. See [SHADCN_SETUP.md](./SHADCN_SETUP.md) for details on how to use ShadCN components in your app.
|
||||
|
||||
## Development
|
||||
|
||||
### Running locally
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "src/components",
|
||||
"utils": "src/lib/utils",
|
||||
"ui": "src/components/ui",
|
||||
"lib": "src/lib",
|
||||
"hooks": "src/hooks"
|
||||
"lib": "src/client",
|
||||
"components": "src/client/components",
|
||||
"ui": "src/client/components/ui",
|
||||
"utils": "src/client/utils",
|
||||
"hooks": "src/client/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type AuthUser } from "wasp/auth";
|
||||
import { getDailyStats, useQuery } from "wasp/client/operations";
|
||||
import { cn } from "../../../lib/utils";
|
||||
import { cn } from "../../../client/utils";
|
||||
import DefaultLayout from "../../layout/DefaultLayout";
|
||||
import RevenueAndProfitChart from "./RevenueAndProfitChart";
|
||||
import SourcesTable from "./SourcesTable";
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { ArrowDown, ArrowUp, Eye } from "lucide-react";
|
||||
import { Card, CardContent, CardHeader } from "../../../components/ui/card";
|
||||
import { cn } from "../../../lib/utils";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
} from "../../../client/components/ui/card";
|
||||
import { cn } from "../../../client/utils";
|
||||
|
||||
type PageViewsStats = {
|
||||
totalPageViews: number | undefined;
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { ArrowDown, ArrowUp, ShoppingBag } from "lucide-react";
|
||||
import { useMemo } from "react";
|
||||
import { type DailyStatsProps } from "../../../analytics/stats";
|
||||
import { Card, CardContent, CardHeader } from "../../../components/ui/card";
|
||||
import { cn } from "../../../lib/utils";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
} from "../../../client/components/ui/card";
|
||||
import { cn } from "../../../client/utils";
|
||||
|
||||
const TotalPayingUsersCard = ({ dailyStats, isLoading }: DailyStatsProps) => {
|
||||
const isDeltaPositive = useMemo(() => {
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { ArrowDown, ArrowUp, ShoppingCart } from "lucide-react";
|
||||
import { useMemo } from "react";
|
||||
import { type DailyStatsProps } from "../../../analytics/stats";
|
||||
import { Card, CardContent, CardHeader } from "../../../components/ui/card";
|
||||
import { cn } from "../../../lib/utils";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
} from "../../../client/components/ui/card";
|
||||
import { cn } from "../../../client/utils";
|
||||
|
||||
const TotalRevenueCard = ({
|
||||
dailyStats,
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { ArrowUp, UsersRound } from "lucide-react";
|
||||
import { useMemo } from "react";
|
||||
import { type DailyStatsProps } from "../../../analytics/stats";
|
||||
import { Card, CardContent, CardHeader } from "../../../components/ui/card";
|
||||
import { cn } from "../../../lib/utils";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
} from "../../../client/components/ui/card";
|
||||
import { cn } from "../../../client/utils";
|
||||
|
||||
const TotalSignupsCard = ({ dailyStats, isLoading }: DailyStatsProps) => {
|
||||
const isDeltaPositive = useMemo(() => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "../../../components/ui/dropdown-menu";
|
||||
} from "../../../client/components/ui/dropdown-menu";
|
||||
|
||||
const DropdownEditDelete = () => {
|
||||
return (
|
||||
|
||||
@@ -7,19 +7,19 @@ import {
|
||||
useQuery,
|
||||
} from "wasp/client/operations";
|
||||
import { type User } from "wasp/entities";
|
||||
import useDebounce from "../../../client/hooks/useDebounce";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { Checkbox } from "../../../components/ui/checkbox";
|
||||
import { Input } from "../../../components/ui/input";
|
||||
import { Label } from "../../../components/ui/label";
|
||||
import { Button } from "../../../client/components/ui/button";
|
||||
import { Checkbox } from "../../../client/components/ui/checkbox";
|
||||
import { Input } from "../../../client/components/ui/input";
|
||||
import { Label } from "../../../client/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "../../../components/ui/select";
|
||||
import { Switch } from "../../../components/ui/switch";
|
||||
} from "../../../client/components/ui/select";
|
||||
import { Switch } from "../../../client/components/ui/switch";
|
||||
import useDebounce from "../../../client/hooks/useDebounce";
|
||||
import { SubscriptionStatus } from "../../../payment/plans";
|
||||
import LoadingSpinner from "../../layout/LoadingSpinner";
|
||||
import DropdownEditDelete from "./DropdownEditDelete";
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { FileText, Mail, Upload, User } from "lucide-react";
|
||||
import { FormEvent } from "react";
|
||||
import { type AuthUser } from "wasp/auth";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { Button } from "../../../client/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../../../components/ui/card";
|
||||
import { Input } from "../../../components/ui/input";
|
||||
import { Label } from "../../../components/ui/label";
|
||||
import { Textarea } from "../../../components/ui/textarea";
|
||||
} from "../../../client/components/ui/card";
|
||||
import { Input } from "../../../client/components/ui/input";
|
||||
import { Label } from "../../../client/components/ui/label";
|
||||
import { Textarea } from "../../../client/components/ui/textarea";
|
||||
import Breadcrumb from "../../layout/Breadcrumb";
|
||||
import DefaultLayout from "../../layout/DefaultLayout";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Heart, Plus, Trash2 } from "lucide-react";
|
||||
import { type AuthUser } from "wasp/auth";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { Button } from "../../../client/components/ui/button";
|
||||
import Breadcrumb from "../../layout/Breadcrumb";
|
||||
import DefaultLayout from "../../layout/DefaultLayout";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type AuthUser } from "wasp/auth";
|
||||
import DarkModeSwitcher from "../../client/components/DarkModeSwitcher";
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../client/utils";
|
||||
import { UserDropdown } from "../../user/UserDropdown";
|
||||
import MessageButton from "../dashboards/messages/MessageButton";
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { NavLink, useLocation } from "react-router-dom";
|
||||
import Logo from "../../client/static/logo.webp";
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../client/utils";
|
||||
import SidebarLinkGroup from "./SidebarLinkGroup";
|
||||
|
||||
interface SidebarProps {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { Outlet, useLocation } from "react-router-dom";
|
||||
import { routes } from "wasp/client/router";
|
||||
import { Toaster } from "../components/ui/toaster";
|
||||
import { Toaster } from "../client/components/ui/toaster";
|
||||
import "./Main.css";
|
||||
import NavBar from "./components/NavBar/NavBar";
|
||||
import {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Moon, Sun } from "lucide-react";
|
||||
import { Label } from "../../components/ui/label";
|
||||
import { cn } from "../../lib/utils";
|
||||
import { Label } from "../../client/components/ui/label";
|
||||
import useColorMode from "../hooks/useColorMode";
|
||||
import { cn } from "../utils";
|
||||
|
||||
const DarkModeSwitcher = () => {
|
||||
const [colorMode, setColorMode] = useColorMode();
|
||||
|
||||
@@ -9,13 +9,13 @@ import {
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
SheetTrigger,
|
||||
} from "../../../components/ui/sheet";
|
||||
import { cn } from "../../../lib/utils";
|
||||
} from "../../../client/components/ui/sheet";
|
||||
import { throttleWithTrailingInvocation } from "../../../shared/utils";
|
||||
import { UserDropdown } from "../../../user/UserDropdown";
|
||||
import { UserMenuItems } from "../../../user/UserMenuItems";
|
||||
import { useIsLandingPage } from "../../hooks/useIsLandingPage";
|
||||
import logo from "../../static/logo.webp";
|
||||
import { cn } from "../../utils";
|
||||
import DarkModeSwitcher from "../DarkModeSwitcher";
|
||||
import { Announcement } from "./Announcement";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Accordion = AccordionPrimitive.Root;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const alertVariants = cva(
|
||||
"relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Avatar = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Root>,
|
||||
@@ -2,10 +2,10 @@ import { Slot } from "@radix-ui/react-slot";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { cva, VariantProps } from "class-variance-authority";
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const cardVariants = cva(
|
||||
"rounded-xl border shadow hover:shadow-lg transition-all duration-300 xur",
|
||||
@@ -2,7 +2,7 @@ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
||||
import { Check } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Checkbox = React.forwardRef<
|
||||
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
||||
@@ -2,7 +2,7 @@ import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||
import { X } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Dialog = DialogPrimitive.Root;
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const DropdownMenu = DropdownMenuPrimitive.Root;
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
type FieldValues,
|
||||
} from "react-hook-form";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
import { Label } from "./label";
|
||||
|
||||
const Form = FormProvider;
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
|
||||
({ className, type, ...props }, ref) => {
|
||||
@@ -4,7 +4,7 @@ import * as LabelPrimitive from "@radix-ui/react-label";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const labelVariants = cva(
|
||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Progress = React.forwardRef<
|
||||
React.ElementRef<typeof ProgressPrimitive.Root>,
|
||||
@@ -2,7 +2,7 @@ import * as SelectPrimitive from "@radix-ui/react-select";
|
||||
import { Check, ChevronDown, ChevronUp } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Select = SelectPrimitive.Root;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Separator = React.forwardRef<
|
||||
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
||||
@@ -3,7 +3,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { X } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Sheet = SheetPrimitive.Root;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as SwitchPrimitives from "@radix-ui/react-switch";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Switch = React.forwardRef<
|
||||
React.ElementRef<typeof SwitchPrimitives.Root>,
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const Textarea = React.forwardRef<
|
||||
HTMLTextAreaElement,
|
||||
@@ -3,7 +3,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { X } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../utils";
|
||||
|
||||
const ToastProvider = ToastPrimitives.Provider;
|
||||
|
||||
@@ -12,19 +12,19 @@ import { Link, routes } from "wasp/client/router";
|
||||
|
||||
import { ArrowRight, Loader2, Trash2 } from "lucide-react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { Button } from "../components/ui/button";
|
||||
import { Button } from "../client/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../components/ui/card";
|
||||
import { Checkbox } from "../components/ui/checkbox";
|
||||
import { Input } from "../components/ui/input";
|
||||
import { Label } from "../components/ui/label";
|
||||
import { ToastAction } from "../components/ui/toast";
|
||||
import { toast } from "../hooks/use-toast";
|
||||
import { cn } from "../lib/utils";
|
||||
} from "../client/components/ui/card";
|
||||
import { Checkbox } from "../client/components/ui/checkbox";
|
||||
import { Input } from "../client/components/ui/input";
|
||||
import { Label } from "../client/components/ui/label";
|
||||
import { ToastAction } from "../client/components/ui/toast";
|
||||
import { toast } from "../client/hooks/use-toast";
|
||||
import { cn } from "../client/utils";
|
||||
import type {
|
||||
GeneratedSchedule,
|
||||
Task as ScheduleTask,
|
||||
|
||||
@@ -10,9 +10,9 @@ import {
|
||||
import type { File } from "wasp/entities";
|
||||
|
||||
import { Download, Trash } from "lucide-react";
|
||||
import { Alert, AlertDescription } from "../components/ui/alert";
|
||||
import { Button } from "../components/ui/button";
|
||||
import { Card, CardContent, CardTitle } from "../components/ui/card";
|
||||
import { Alert, AlertDescription } from "../client/components/ui/alert";
|
||||
import { Button } from "../client/components/ui/button";
|
||||
import { Card, CardContent, CardTitle } from "../client/components/ui/card";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -20,12 +20,12 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "../components/ui/dialog";
|
||||
import { Input } from "../components/ui/input";
|
||||
import { Label } from "../components/ui/label";
|
||||
import { Progress } from "../components/ui/progress";
|
||||
import { toast } from "../hooks/use-toast";
|
||||
import { cn } from "../lib/utils";
|
||||
} from "../client/components/ui/dialog";
|
||||
import { Input } from "../client/components/ui/input";
|
||||
import { Label } from "../client/components/ui/label";
|
||||
import { Progress } from "../client/components/ui/progress";
|
||||
import { toast } from "../client/hooks/use-toast";
|
||||
import { cn } from "../client/utils";
|
||||
import { uploadFileWithProgress, validateFile } from "./fileUploading";
|
||||
import { ALLOWED_FILE_TYPES } from "./validation";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { forwardRef, useEffect, useRef, useState } from "react";
|
||||
import { Card, CardContent } from "../../components/ui/card";
|
||||
import { Card, CardContent } from "../../client/components/ui/card";
|
||||
|
||||
const EXAMPLES_CAROUSEL_INTERVAL = 3000;
|
||||
const EXAMPLES_CAROUSEL_SCROLL_TIMEOUT = 200;
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "../../components/ui/accordion";
|
||||
} from "../../client/components/ui/accordion";
|
||||
|
||||
interface FAQ {
|
||||
id: number;
|
||||
|
||||
@@ -4,8 +4,8 @@ import {
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardTitle,
|
||||
} from "../../components/ui/card";
|
||||
import { cn } from "../../lib/utils";
|
||||
} from "../../client/components/ui/card";
|
||||
import { cn } from "../../client/utils";
|
||||
import { Feature } from "./Features";
|
||||
import SectionTitle from "./SectionTitle";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Link as WaspRouterLink, routes } from "wasp/client/router";
|
||||
import { Button } from "../../client/components/ui/button";
|
||||
import openSaasBannerDark from "../../client/static/open-saas-banner-dark.svg";
|
||||
import openSaasBannerLight from "../../client/static/open-saas-banner-light.svg";
|
||||
import { Button } from "../../components/ui/button";
|
||||
|
||||
export default function Hero() {
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cn } from "../../lib/utils";
|
||||
import { cn } from "../../client/utils";
|
||||
|
||||
interface FeatureProps {
|
||||
name: string;
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
} from "../../components/ui/card";
|
||||
} from "../../client/components/ui/card";
|
||||
import SectionTitle from "./SectionTitle";
|
||||
|
||||
interface Testimonial {
|
||||
|
||||
@@ -7,15 +7,15 @@ import {
|
||||
getCustomerPortalUrl,
|
||||
useQuery,
|
||||
} from "wasp/client/operations";
|
||||
import { Alert, AlertDescription } from "../components/ui/alert";
|
||||
import { Button } from "../components/ui/button";
|
||||
import { Alert, AlertDescription } from "../client/components/ui/alert";
|
||||
import { Button } from "../client/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
} from "../components/ui/card";
|
||||
import { cn } from "../lib/utils";
|
||||
} from "../client/components/ui/card";
|
||||
import { cn } from "../client/utils";
|
||||
import {
|
||||
PaymentPlanId,
|
||||
paymentPlans,
|
||||
|
||||
@@ -141,7 +141,7 @@ async function handleInvoicePaid(
|
||||
|
||||
function getInvoicePriceId(invoice: Stripe.Invoice): Stripe.Price["id"] {
|
||||
const invoiceLineItems = invoice.lines.data;
|
||||
// We only expect one line item.
|
||||
// We only expect one line item.
|
||||
// If your workflow expects more, you should change this function to handle them.
|
||||
if (invoiceLineItems.length !== 1) {
|
||||
throw new Error("There should be exactly one line item in Stripe invoice");
|
||||
@@ -204,7 +204,7 @@ function getSubscriptionPriceId(
|
||||
subscription: Stripe.Subscription,
|
||||
): Stripe.Price["id"] {
|
||||
const subscriptionItems = subscription.items.data;
|
||||
// We only expect one subscription item.
|
||||
// We only expect one subscription item.
|
||||
// If your workflow expects more, you should change this function to handle them.
|
||||
if (subscriptionItems.length !== 1) {
|
||||
throw new Error(
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { getCustomerPortalUrl, useQuery } from "wasp/client/operations";
|
||||
import { Link as WaspRouterLink, routes } from "wasp/client/router";
|
||||
import type { User } from "wasp/entities";
|
||||
import { Button } from "../components/ui/button";
|
||||
import { Button } from "../client/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "../components/ui/card";
|
||||
import { Separator } from "../components/ui/separator";
|
||||
} from "../client/components/ui/card";
|
||||
import { Separator } from "../client/components/ui/separator";
|
||||
import {
|
||||
PaymentPlanId,
|
||||
SubscriptionStatus,
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "../components/ui/dropdown-menu";
|
||||
} from "../client/components/ui/dropdown-menu";
|
||||
import { userMenuItems } from "./constants";
|
||||
|
||||
export function UserDropdown({ user }: { user: Partial<UserEntity> }) {
|
||||
|
||||
Reference in New Issue
Block a user