chore: types cleanup for react 19 (#44941)

## Problem

While trying to update `react` to version `19`, I noticed type related
errors that can be fixed in version `18`, mostly usage of `JSX.Element`
instead of `ReactNode`.

## Solution

- Use `ReactNode` instead of `JSX.Element`
- Fix some invalid usage of `rechart`

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **Refactor**
* Standardized React component type annotations across the codebase for
improved type consistency and flexibility.
* Updated component prop types to accept a broader range of renderable
content.

* **Bug Fixes**
  * Adjusted chart layout positioning to improve visual alignment.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Gildas Garcia authored and GitHub committed 2026-04-16 15:31:04 +02:00
1 parent 16fd60134d
commit c3119ea1ea
37 files changed
+174 -168

No files matched your search

@@ -26,7 +26,7 @@ import {
} from 'ui-patterns/PageHeader'
import { PageSection, PageSectionContent } from 'ui-patterns/PageSection'
export default function PageLayoutList(): React.JSX.Element {
export default function PageLayoutList() {
const functions = [
{
id: 1,
@@ -1,3 +1,5 @@
import { ReactNode } from 'react'
import { Lint } from '@/data/lint/lint-query'
export enum LINTER_LEVELS {
@@ -9,7 +11,7 @@ export enum LINTER_LEVELS {
export type LintInfo = {
name: string
title: string
icon: JSX.Element
icon: ReactNode
link: (args: { projectRef: string; metadata: Lint['metadata'] }) => string
linkText: string
docsLink: string
@@ -1,3 +1,4 @@
import { ReactNode } from 'react'
import { Admonition } from 'ui-patterns'
import { USAGE_APPROACHING_THRESHOLD } from '@/components/interfaces/Billing/Billing.constants'
@@ -60,7 +61,7 @@ export interface CategoryAttribute {
chartPrefix?: 'Max' | 'Average' | 'Cumulative'
chartSuffix?: string
chartDescription: string
additionalInfo?: (usage?: OrgUsageResponse) => JSX.Element | null
additionalInfo?: (usage?: OrgUsageResponse) => ReactNode | null
}
export type CategoryMetaKey = 'egress' | 'sizeCount' | 'activity' | 'compute' | 'logs'
@@ -3,7 +3,7 @@ import { geoCentroid } from 'd3-geo'
import sumBy from 'lodash/sumBy'
import { ChevronRight } from 'lucide-react'
import { useTheme } from 'next-themes'
import { Fragment, useRef, useState } from 'react'
import { Fragment, useRef, useState, type ReactNode } from 'react'
import { ComposableMap, Geographies, Geography, Marker, ZoomableGroup } from 'react-simple-maps'
import {
Alert_Shadcn_,
@@ -576,7 +576,7 @@ export const RequestsByCountryMapRenderer = (
if (code) present.add(code)
}
const markers: JSX.Element[] = []
const markers: ReactNode[] = []
for (const iso2 in countsByIso2) {
const count = countsByIso2[iso2]
if (count <= 0) continue
@@ -1,4 +1,5 @@
import { type inferParserType } from 'nuqs'
import type { inferParserType } from 'nuqs'
import type { ReactNode } from 'react'
import { LOG_TYPES, SEARCH_PARAMS_PARSER } from './UnifiedLogs.constants'
@@ -50,7 +51,7 @@ export type SheetField<TData, TMeta = Record<string, unknown>> = {
totalRowsFetched: number
} & TMeta
}
) => JSX.Element | null | string
) => ReactNode
condition?: (props: TData) => boolean
className?: string
skeletonClassName?: string
@@ -1,7 +1,8 @@
import type { ReactNode } from 'react'
import { Badge, Card } from 'ui'
export const ActionCard = (card: {
icon: JSX.Element
icon: ReactNode
title: string
description: string
bgColor: string
@@ -1,8 +1,8 @@
import { PropsWithChildren } from 'react'
import type { PropsWithChildren, ReactNode } from 'react'
interface TableProps {
body: JSX.Element | JSX.Element[]
head?: JSX.Element | JSX.Element[]
body: ReactNode
head?: ReactNode
className?: string
containerClassName?: string
borderless?: boolean
@@ -1,4 +1,4 @@
import type { PropsWithChildren } from 'react'
import type { PropsWithChildren, ReactNode } from 'react'
import {
cn,
Collapsible,
@@ -8,8 +8,8 @@ import {
type ToolProps = PropsWithChildren<{
className?: string
label: string | JSX.Element
icon?: JSX.Element
label: ReactNode
icon?: ReactNode
}>
export function Tool({ className, label, icon, children }: ToolProps) {
+3 -3
View File
@@ -1,11 +1,11 @@
import { JSX, ReactNode } from 'react'
import type { ReactNode } from 'react'
import { Badge, Card, cn } from 'ui'
export const ActionCard = (card: {
icon: JSX.Element
icon: ReactNode
title: string
bgColor?: string
description?: string | ReactNode
description?: ReactNode
isBeta?: boolean
className?: string
onClick?: () => void
@@ -1,5 +1,5 @@
import dayjs from 'dayjs'
import { FC, PropsWithChildren, useMemo } from 'react'
import { useMemo, type FC, type ReactElement } from 'react'
import { ResponsiveContainer } from 'recharts'
import { DateTimeFormats } from './Charts.constants'
@@ -232,7 +232,7 @@ export const useChartSize = (
}
) => {
const minHeight = sizeMap[size]
const Container: FC<PropsWithChildren & { className?: string }> = useMemo(
const Container: FC<{ children: ReactElement; className?: string }> = useMemo(
() =>
({ className, children }) => (
<ResponsiveContainer
@@ -241,7 +241,7 @@ export const useChartSize = (
minHeight={minHeight}
width="100%"
>
{children as JSX.Element}
{children}
</ResponsiveContainer>
),
[size]
@@ -664,13 +664,13 @@ export function ComposedChart({
}}
/>
</RechartComposedChart>
<ChartHighlightActions
chartHighlight={chartHighlight}
updateDateRange={updateDateRange}
actions={highlightActions}
chartId={chartId}
/>
</Container>
<ChartHighlightActions
chartHighlight={chartHighlight}
updateDateRange={updateDateRange}
actions={highlightActions}
chartId={chartId}
/>
{data && (
<div
className="text-foreground-lighter -mt-9 flex items-center justify-between text-xs"
@@ -1,3 +1,5 @@
import type { ReactNode } from 'react'
// TODO: we could type the value(!) especially when using enums
export type Option = {
label: string
@@ -18,7 +20,7 @@ export type Input = {
export type Checkbox = {
type: 'checkbox'
component?: (props: Option) => JSX.Element | null
component?: (props: Option) => ReactNode
options?: Option[]
}
+3 -3
View File
@@ -1,8 +1,8 @@
import { ReactText } from 'react'
import type { ReactNode } from 'react'
interface Props {
icon: JSX.Element
text: ReactText
icon: ReactNode
text: ReactNode
}
const FormBoxEmpty = ({ icon, text }: Props) => {
+1 -1
View File
@@ -22,7 +22,7 @@ import { cn, Skeleton } from 'ui'
// any here is intentional to allow for generic components and does not affect
// type safety of the wrapped component
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const typedMemo = <Component extends (props: any) => JSX.Element | null>(
const typedMemo = <Component extends (props: any) => ReactNode>(
component: Component,
propsAreEqual?: (
prevProps: Readonly<Parameters<Component>[0]>,
+2 -2
View File
@@ -1,11 +1,11 @@
import { Megaphone } from 'lucide-react'
import { forwardRef, PropsWithChildren, ReactNode } from 'react'
import { forwardRef, type PropsWithChildren, type ReactNode } from 'react'
import { Badge, Button, cn, Loading } from 'ui'
interface PanelProps {
className?: string
id?: string
footer?: JSX.Element | false
footer?: ReactNode
loading?: boolean
noMargin?: boolean
title?: ReactNode | false
@@ -1,12 +1,11 @@
import React, { FC } from 'react'
import SectionContainer from '~/components/Layouts/SectionContainer'
import UsersGrowthChart from '~/components/UsersGrowthChart'
import React, { type FC, type ReactNode } from 'react'
interface Props {
id: string
heading: string | JSX.Element
subheading: string | JSX.Element
heading: ReactNode
subheading: ReactNode
highlights: Highlight[]
}
+5 -5
View File
@@ -1,14 +1,14 @@
import type { LucideIcon } from 'lucide-react'
import React, { FC } from 'react'
import React, { type FC, type ReactNode } from 'react'
import { TextLink } from 'ui-patterns/TextLink'
import SectionContainer from '@/components/Layouts/SectionContainer'
export interface SecuritySectionProps {
id: string
label: string | JSX.Element
heading: string | JSX.Element
subheading: string | JSX.Element
label: ReactNode
heading: ReactNode
subheading: ReactNode
features: FeatureProps[]
cta: {
label: string
@@ -19,7 +19,7 @@ export interface SecuritySectionProps {
export type Story = {
url: string
heading: string
subheading: string | JSX.Element
subheading: ReactNode
}
type FeatureProps = {
+4 -6
View File
@@ -1,14 +1,12 @@
import React, { FC } from 'react'
import { cn } from 'ui'
import SectionContainer from '~/components/Layouts/SectionContainer'
import type { LucideIcon } from 'lucide-react'
import React, { type FC, type ReactNode } from 'react'
import { cn } from 'ui'
interface Props {
id: string
label?: string | JSX.Element
heading: string | JSX.Element
label?: ReactNode
heading: ReactNode
features: Feature[]
}
+4 -4
View File
@@ -3,7 +3,7 @@ import 'swiper/css'
import type { LucideIcon } from 'lucide-react'
import Image from 'next/image'
import Link from 'next/link'
import React, { FC } from 'react'
import React, { type FC, type ReactNode } from 'react'
import { Swiper, SwiperSlide } from 'swiper/react'
import { TextLink } from 'ui-patterns/TextLink'
@@ -12,8 +12,8 @@ import Panel from '@/components/Panel'
interface Props {
id: string
label?: string | JSX.Element
heading?: string | JSX.Element
label?: ReactNode
heading?: ReactNode
stories?: Story[]
highlights?: Highlight[]
}
@@ -23,7 +23,7 @@ export type Story = {
url: string
target?: '_blank' | string
heading?: string
subheading?: string | JSX.Element
subheading?: ReactNode
}
type Highlight = {
+4 -4
View File
@@ -1,9 +1,9 @@
import { useEffect, useState } from 'react'
import { AnimatePresence, motion, useAnimation } from 'framer-motion'
import { useEffect, useState, type ReactNode } from 'react'
import { cn } from 'ui'
interface TabProps {
label: string | JSX.Element
label: ReactNode
isActive: boolean
onClick: VoidFunction
}
@@ -22,9 +22,9 @@ const Tab = ({ isActive, label, onClick }: TabProps) => (
)
interface Tab {
label: string | JSX.Element
label: ReactNode
paragraph?: string
panel: JSX.Element
panel: ReactNode
}
interface Props {
@@ -1,4 +1,4 @@
import React, { FC } from 'react'
import React, { type FC, type ReactNode } from 'react'
import { cn } from 'ui'
import { TextLink } from 'ui-patterns/TextLink'
@@ -15,9 +15,9 @@ select
`
interface Props {
id: string
label: string | JSX.Element
heading: string | JSX.Element
subheading: string | JSX.Element
label: ReactNode
heading: ReactNode
subheading: ReactNode
className?: string
cta?: {
label: string
@@ -1,4 +1,4 @@
import React, { FC } from 'react'
import React, { type FC, type ReactNode } from 'react'
import { cn } from 'ui'
import { TextLink } from 'ui-patterns/TextLink'
@@ -22,9 +22,9 @@ const message = await queues.rpc("pop", {
interface Props {
id: string
label: string | JSX.Element
heading: string | JSX.Element
subheading: string | JSX.Element
label: ReactNode
heading: ReactNode
subheading: ReactNode
className?: string
cta?: {
label: string
@@ -1,4 +1,4 @@
import React, { FC } from 'react'
import React, { type FC, type ReactNode } from 'react'
import { cn } from 'ui'
import { TextLink } from 'ui-patterns/TextLink'
@@ -17,9 +17,9 @@ select * from pgmq.pop('my_special_queue');
`
interface Props {
id: string
label: string | JSX.Element
heading: string | JSX.Element
subheading: string | JSX.Element
label: ReactNode
heading: ReactNode
subheading: ReactNode
className?: string
cta?: {
label: string
@@ -1,10 +1,11 @@
'use client'
import classNames from 'classnames'
import { Fragment, useMemo, useState } from 'react'
import { Collapsible } from 'ui'
import { Check } from './PricingIcons'
import { ChevronUp } from 'lucide-react'
import { Fragment, useMemo, useState, type ReactNode } from 'react'
import { Collapsible } from 'ui'
import { Check } from './PricingIcons'
interface PricingAddOnTableProps {
pricing: {
@@ -18,7 +19,7 @@ interface PricingAddOnTableProps {
}[]
}[]
}
icon: JSX.Element
icon: ReactNode
}
const PricingAddOnTable = ({ icon, pricing }: PricingAddOnTableProps) => {
@@ -1,4 +1,4 @@
import React, { FC } from 'react'
import React, { type FC, type ReactNode } from 'react'
import { cn } from 'ui'
import { TextLink } from 'ui-patterns/TextLink'
@@ -6,9 +6,9 @@ import SectionContainer from '@/components/Layouts/SectionContainer'
interface Props {
id: string
label: string | JSX.Element
heading: string | JSX.Element
subheading: string | JSX.Element
label: ReactNode
heading: ReactNode
subheading: ReactNode
image?: any
className?: string
cta?: {
@@ -1,16 +1,17 @@
import React from 'react'
import { Button, cn } from 'ui'
import Link from 'next/link'
import ProductIcon from '../ProductIcon'
import SectionContainer from '../Layouts/SectionContainer'
import { CTA } from '~/types/common'
import Link from 'next/link'
import React, { Children, type ReactNode } from 'react'
import { Button, cn } from 'ui'
import SectionContainer from '../Layouts/SectionContainer'
import ProductIcon from '../ProductIcon'
// to do: move types to be global
// then solutions.types.ts should extend this
interface Props {
label?: string | React.ReactNode
h1: string | React.ReactNode
subheader?: string[] | React.ReactNode[]
label?: ReactNode
h1: ReactNode
subheader?: ReactNode
icon?: string
title?: string
image?: React.ReactNode
@@ -54,7 +55,7 @@ const ProductHeader = ({ footerPosition = 'left', ...props }: Props) => (
</h1>
{props.subheader && (
<div className="">
{props.subheader.map((subheader, i) => {
{Children.map(props.subheader, (subheader, i) => {
return (
<p className="p lg:text-lg max-w-lg lg:max-w-none" key={i}>
{subheader}
+5 -6
View File
@@ -1,8 +1,7 @@
import Link from 'next/link'
import React, { FC } from 'react'
import { cn } from 'ui'
import SectionContainer from '~/components/Layouts/SectionContainer'
import Link from 'next/link'
import React, { type FC, type ReactNode } from 'react'
import { cn } from 'ui'
interface Props {
id: string
@@ -17,9 +16,9 @@ interface Props {
type Quote = {
text: string
author: string
logo?: string | JSX.Element
logo?: ReactNode
role: string
avatar?: string | JSX.Element
avatar?: ReactNode
link?: string
}
@@ -1,10 +1,10 @@
import 'swiper/css'
import React, { useState, useEffect, useRef } from 'react'
import { LazyMotion, domAnimation, m, useAnimation, useInView } from 'framer-motion'
import { cn } from 'ui'
import { Swiper, SwiperSlide } from 'swiper/react'
import { useBreakpoint } from 'common'
import { domAnimation, LazyMotion, m, useAnimation, useInView } from 'framer-motion'
import React, { useEffect, useRef, useState, type ReactNode } from 'react'
import { Swiper, SwiperSlide } from 'swiper/react'
import { cn } from 'ui'
interface TabProps {
label: string | React.ReactNode
@@ -66,9 +66,9 @@ const Tab = ({ isActive, label, paragraph, onClick, progress, intervalDuration }
}
interface Tab {
label: string | React.ReactNode
paragraph?: string | React.ReactNode
panel?: JSX.Element
label: ReactNode
paragraph?: ReactNode
panel?: ReactNode
code?: string
}
@@ -1,14 +1,14 @@
import 'swiper/css'
import { AnimatePresence, motion, useAnimation } from 'framer-motion'
import Image from 'next/image'
import Link from 'next/link'
import { ReactNode, useEffect, useState } from 'react'
import { Swiper, SwiperSlide } from 'swiper/react'
import { Button } from 'ui'
import CodeBlock from '~/components/CodeBlock/CodeBlock'
import SectionContainer from '~/components/Layouts/SectionContainer'
import { AnimatePresence, motion, useAnimation } from 'framer-motion'
import { ArrowUpRight } from 'lucide-react'
import Image from 'next/image'
import Link from 'next/link'
import { useEffect, useState, type ReactNode } from 'react'
import { Swiper, SwiperSlide } from 'swiper/react'
import { Button } from 'ui'
interface TabProps {
label: string
@@ -58,13 +58,13 @@ const Tab = ({ isActive, label, paragraph, onClick, progress, intervalDuration }
interface Tab {
label: string
paragraph?: string
panel?: JSX.Element
panel?: ReactNode
colabUrl: string
code?: string
}
interface Props {
title: string | ReactNode
title: ReactNode
paragraph: string
cta?: {
label?: string
@@ -1,12 +1,11 @@
import React, { FC } from 'react'
import SectionContainer from '~/components/Layouts/SectionContainer'
import UsersGrowthChart from '~/components/UsersGrowthChart'
import React, { type FC, type ReactNode } from 'react'
export interface ResultsSectionProps {
id: string
heading: string | JSX.Element
subheading: string | JSX.Element
heading: ReactNode
subheading: ReactNode
highlights: Highlight[]
}
+4 -4
View File
@@ -1,13 +1,13 @@
import React, { FC } from 'react'
import SectionContainer from '~/components/Layouts/SectionContainer'
import Panel from '../Panel'
import type { Testimonials } from '~/data/solutions/solutions.utils'
import React, { type FC, type ReactNode } from 'react'
import Panel from '../Panel'
export type Story = {
url: string
heading: string
subheading: string | JSX.Element
subheading: ReactNode
}
const EnterpriseSecurity: FC<Testimonials> = (props) => {
@@ -1,12 +1,11 @@
import React, { FC } from 'react'
import SectionContainer from '~/components/Layouts/SectionContainer'
import UsersGrowthChart from '~/components/UsersGrowthChart'
import React, { type FC, type ReactNode } from 'react'
export interface PerfectTimingProps {
id: string
heading: string | JSX.Element
subheading: string | JSX.Element
heading: ReactNode
subheading: ReactNode
highlights: Highlight[]
}
+2 -1
View File
@@ -1,3 +1,4 @@
import type { ReactNode } from 'react'
import { products } from 'shared-data'
import { PRODUCT_NAMES, PRODUCT_SHORTNAMES } from 'shared-data/products'
@@ -5,7 +6,7 @@ export type ProductType = {
[key: string]: {
name: string
icon: string
description: string | JSX.Element
description: ReactNode
description_short: string
label: string
url: string
@@ -1,7 +1,7 @@
import { useBreakpoint } from 'common'
import { LucideIcon } from 'lucide-react'
import Link from 'next/link'
import type { ComponentType, SVGProps } from 'react'
import type { ComponentType, ReactNode, SVGProps } from 'react'
import { cn } from 'ui'
import z from 'zod'
@@ -43,9 +43,9 @@ export interface Metadata {
export interface HeroSection {
id: string
title: string
h1: JSX.Element
subheader: JSX.Element[]
image: JSX.Element
h1: ReactNode
subheader: ReactNode
image: ReactNode
className?: string
sectionContainerClassName?: string
icon?: string
@@ -66,7 +66,7 @@ export interface Quote {
icon?: string
author: string
authorTitle?: string
quote: JSX.Element
quote: ReactNode
avatar: string
}
@@ -77,8 +77,8 @@ export interface Quotes {
export interface Highlight {
icon?: IconType
heading: string | JSX.Element
subheading: string | JSX.Element
heading: ReactNode
subheading: ReactNode
url?: string
}
@@ -86,16 +86,16 @@ export interface Feature {
id?: string
icon?: string
iconNoStroke?: boolean
heading: string | JSX.Element
subheading: string | JSX.Element
img?: JSX.Element
heading: ReactNode
subheading: ReactNode
img?: ReactNode
}
export interface FeaturesSection {
id: string
label?: string
heading: JSX.Element
subheading?: string | JSX.Element
heading: ReactNode
subheading?: ReactNode
features: Feature[]
className?: string
// {
@@ -106,7 +106,7 @@ export interface FeaturesSection {
export interface Testimonials {
id: string
label: string
heading: JSX.Element
heading: ReactNode
videos: {
[key: string]: {
url: string
@@ -117,7 +117,7 @@ export interface Testimonials {
export interface CTASection {
id: string
label: string
heading: JSX.Element | string
heading: ReactNode
subheading: string
cta: {
label: string
+4 -3
View File
@@ -18,6 +18,7 @@ import {
UserX,
} from 'lucide-react'
import dynamic from 'next/dynamic'
import type { ReactNode } from 'react'
import { PRODUCT_SHORTNAMES } from 'shared-data/products'
import { Image } from 'ui-patterns/Image'
@@ -45,9 +46,9 @@ interface Quote {
text: string
author: string
role: string
logo?: string | JSX.Element
logo?: ReactNode
link?: string
avatar?: string | JSX.Element
avatar?: ReactNode
}
interface AIBuilderEcosystemSection {
@@ -918,7 +919,7 @@ const data: () => {
'## Overview of implementing Supabase Auth SSR\n1. Install @supabase/supabase-js and...',
code: `1. Install @supabase/supabase-js and @supabase/ssr packages.
2. Set up environment variables.
3. Write two utility functions with \u0060createClient\u0060 functions to create a browser client and a server client.
3. Write two utility functions with \u0060createClient\u0060 functions to create a browser client and a server client.
4. Hook up middleware to refresh auth tokens
`,
language: 'markdown',
+17 -17
View File
@@ -1,7 +1,7 @@
import { useBreakpoint } from 'common'
import { LucideIcon } from 'lucide-react'
import Link from 'next/link'
import type { ComponentType, SVGProps } from 'react'
import type { ComponentType, ReactNode, SVGProps } from 'react'
import { cn } from 'ui'
export type HeroIcon = ComponentType<SVGProps<SVGSVGElement>>
@@ -15,9 +15,9 @@ export interface Metadata {
export interface HeroSection {
id: string
title: string
h1: JSX.Element
subheader: JSX.Element[]
image: JSX.Element | undefined
h1: ReactNode
subheader: ReactNode
image: ReactNode
className?: string
sectionContainerClassName?: string
icon?: string
@@ -30,7 +30,7 @@ export interface HeroSection {
name: string
image: string
}[]
footer?: React.ReactNode
footer?: ReactNode
footerPosition?: 'left' | 'right' | 'bottom'
}
@@ -38,7 +38,7 @@ export interface Quote {
icon?: string
author: string
authorTitle?: string
quote: JSX.Element
quote: ReactNode
avatar: string
}
@@ -49,8 +49,8 @@ export interface Quotes {
export interface Highlight {
icon?: IconType
heading: string | JSX.Element
subheading: string | JSX.Element
heading: ReactNode
subheading: ReactNode
url?: string
}
@@ -58,15 +58,15 @@ export interface Feature {
id?: string
icon?: IconType | string
iconNoStroke?: boolean
heading: string | JSX.Element
subheading: string | JSX.Element
img?: JSX.Element
heading: ReactNode
subheading: ReactNode
img?: ReactNode
}
export interface FeaturesSection {
id: string
label?: string
heading: string | JSX.Element
heading: ReactNode
subheading?: string
features: Feature[]
// {
@@ -77,7 +77,7 @@ export interface FeaturesSection {
export interface Testimonials {
id: string
label: string
heading: JSX.Element
heading: ReactNode
videos: {
[key: string]: {
url: string
@@ -88,7 +88,7 @@ export interface Testimonials {
export interface CTASection {
id: string
label: string
heading: JSX.Element | string
heading: ReactNode | string
subheading: string
cta: {
label: string
@@ -99,13 +99,13 @@ export interface CTASection {
export interface FrameworkLinkProps {
name: string
icon: string | React.ReactNode
icon: string | ReactNode
docs: string
}
export interface PostGridProps {
header: React.ReactNode
subheader: React.ReactNode
header: ReactNode
subheader: ReactNode
}
export const FrameworkLink = ({ framework }: { framework: FrameworkLinkProps }) => {
+16 -15
View File
@@ -1,14 +1,15 @@
import DotGrid from '~/components/AIDemo/DotGrid'
import { AIDemoPanel } from '~/components/AIDemo/Panel'
import { SqlSnippet } from '~/components/AIDemo/SqlSnippet'
import { useIsLoggedIn, useIsUserLoading } from 'common'
import { motion } from 'framer-motion'
import { NextSeo } from 'next-seo'
import dynamic from 'next/dynamic'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { useEffect, useState, type ReactNode } from 'react'
import { Button } from 'ui'
import DotGrid from '~/components/AIDemo/DotGrid'
import { AIDemoPanel } from '~/components/AIDemo/Panel'
import { SqlSnippet } from '~/components/AIDemo/SqlSnippet'
import { EASE_OUT } from '../lib/animations'
const DefaultLayout = dynamic(() => import('~/components/Layouts/Default'))
@@ -17,9 +18,9 @@ const SectionContainer = dynamic(() => import('~/components/Layouts/SectionConta
interface Message {
id: string
role: 'user' | 'assistant'
content: string | JSX.Element
content: ReactNode
createdAt: Date
render?: JSX.Element
render?: ReactNode
}
const welcomeMessages = [
@@ -192,14 +193,14 @@ RETURNS INTEGER AS $$
DECLARE
total_points INTEGER;
BEGIN
SELECT
SELECT
COALESCE(
(SELECT COUNT(*) * 10 FROM posts WHERE author_id = user_id) + -- 10 points per post
(SELECT COUNT(*) * 5 FROM comments WHERE user_id = user_id) + -- 5 points per comment
(SELECT COUNT(*) * 2 FROM post_likes WHERE user_id = user_id), -- 2 points per like
0
) INTO total_points;
RETURN total_points;
END;
$$ LANGUAGE plpgsql;`}
@@ -236,16 +237,16 @@ FOR SELECT
USING (
team_id IN (
-- User can see members of teams they belong to
SELECT team_id
FROM team_members
SELECT team_id
FROM team_members
WHERE user_id = auth.uid()
)
OR
OR
-- Team admins can see all members
EXISTS (
SELECT 1
FROM team_admins
WHERE user_id = auth.uid()
SELECT 1
FROM team_admins
WHERE user_id = auth.uid()
AND team_id = team_members.team_id
)
);`}
@@ -272,7 +273,7 @@ USING (
<SqlSnippet
id="projects-sql"
title="Get All Projects SQL"
sql={`SELECT
sql={`SELECT
p.id,
p.name,
p.description,