mirror of
https://github.com/BillyOutlast/posthog.com.git
synced 2026-02-04 03:11:21 +01:00
static roadmap items on ai page
This commit is contained in:
@@ -162,6 +162,8 @@ export const sourceNodes: GatsbyNode['sourceNodes'] = async ({ actions, createCo
|
||||
media: cloudinaryMedia,
|
||||
type: category,
|
||||
year,
|
||||
projectedCompletion,
|
||||
dateCompleted,
|
||||
...other,
|
||||
}
|
||||
const roadmapNode = {
|
||||
|
||||
156
src/components/AI/CustomRoadmapSlide.tsx
Normal file
156
src/components/AI/CustomRoadmapSlide.tsx
Normal file
@@ -0,0 +1,156 @@
|
||||
import React from 'react'
|
||||
import Markdown from 'components/Squeak/components/Markdown'
|
||||
import { IconCheck } from '@posthog/icons'
|
||||
import Link from 'components/Link'
|
||||
import { graphql, useStaticQuery } from 'gatsby'
|
||||
import { useRoadmaps } from 'hooks/useRoadmaps'
|
||||
|
||||
interface RoadmapItem {
|
||||
id: string
|
||||
strapiID: string
|
||||
title: string
|
||||
description: string
|
||||
projectedCompletion?: string
|
||||
complete?: boolean
|
||||
}
|
||||
|
||||
export default function CustomRoadmapSlide(): JSX.Element {
|
||||
const { roadmaps: clientRoadmaps } = useRoadmaps({
|
||||
params: {
|
||||
filters: {
|
||||
$or: [
|
||||
{
|
||||
teams: {
|
||||
name: {
|
||||
$eq: 'PostHog AI',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})
|
||||
const { roadmaps } = useStaticQuery(graphql`
|
||||
{
|
||||
roadmaps: allRoadmap(
|
||||
filter: { teams: { data: { elemMatch: { attributes: { name: { eq: "PostHog AI" } } } } } }
|
||||
) {
|
||||
nodes {
|
||||
id
|
||||
strapiID
|
||||
title
|
||||
description
|
||||
projectedCompletion
|
||||
complete
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
const underConsideration = roadmaps.nodes.filter(
|
||||
(roadmap: any) => !roadmap.projectedCompletion && !roadmap.complete
|
||||
)
|
||||
const inProgress = roadmaps.nodes.filter((roadmap: any) => roadmap.projectedCompletion && !roadmap.complete)
|
||||
const shipped = roadmaps.nodes.filter((roadmap: any) => roadmap.complete)
|
||||
|
||||
return (
|
||||
<div data-scheme="primary" className="h-full bg-primary text-primary p-4 @md:p-8 overflow-auto">
|
||||
<h2 className="text-3xl @md:text-4xl font-bold mb-6 text-center">Roadmap</h2>
|
||||
|
||||
<div className="grid @lg:grid-cols-3 gap-4 max-w-7xl mx-auto">
|
||||
{/* Under Consideration */}
|
||||
<div className="border border-primary rounded overflow-hidden">
|
||||
<h3 className="text-sm @md:text-base text-center bg-accent px-4 py-2 mb-0 font-semibold">
|
||||
Under consideration
|
||||
</h3>
|
||||
<div className="divide-y divide-primary overflow-y-auto">
|
||||
{underConsideration
|
||||
.filter((r) => !!r.description?.trim())
|
||||
.slice(0, 3)
|
||||
.map((roadmap: RoadmapItem) => {
|
||||
const clientRoadmap = clientRoadmaps.find((r: any) => r.id === roadmap.strapiID)
|
||||
const likeCount = clientRoadmap?.attributes?.likes?.data?.length || 0
|
||||
return (
|
||||
<div key={roadmap.id} className="p-3">
|
||||
<div className="flex gap-2">
|
||||
<div className="shrink-0">
|
||||
<div className="bg-[#F5E2B2] rounded px-2 py-1 text-xs font-semibold">
|
||||
<span className={clientRoadmaps?.length > 0 ? '' : 'opacity-0'}>
|
||||
{likeCount}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="text-sm font-bold mb-1 leading-tight truncate">
|
||||
{roadmap.title}
|
||||
</h4>
|
||||
<div className="text-xs line-clamp-2">
|
||||
<Markdown>{roadmap.description}</Markdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* In Progress */}
|
||||
<div className="border border-primary rounded overflow-hidden">
|
||||
<h3 className="text-sm @md:text-base text-center bg-orange text-white px-4 py-2 mb-0 font-semibold">
|
||||
In progress
|
||||
</h3>
|
||||
<div className="divide-y divide-primary overflow-y-auto">
|
||||
{inProgress.slice(0, 3).map((roadmap: RoadmapItem) => (
|
||||
<div key={roadmap.id} className="p-3">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="text-sm font-bold mb-1 leading-tight truncate">
|
||||
{roadmap.title}
|
||||
</h4>
|
||||
<div className="text-xs line-clamp-2">
|
||||
<Markdown>{roadmap.description}</Markdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Shipped */}
|
||||
<div className="border border-primary rounded overflow-hidden">
|
||||
<h3 className="text-sm @md:text-base text-center bg-green px-4 py-2 mb-0 font-semibold text-white">
|
||||
Shipped
|
||||
</h3>
|
||||
<div className="divide-y divide-primary overflow-y-auto">
|
||||
{shipped.slice(0, 3).map((roadmap: RoadmapItem) => (
|
||||
<div key={roadmap.id} className="p-3">
|
||||
<div className="flex gap-2">
|
||||
<div className="shrink-0">
|
||||
<IconCheck className="w-4 h-4 text-green" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="text-sm font-bold mb-1 leading-tight">{roadmap.title}</h4>
|
||||
<div className="text-xs line-clamp-2">
|
||||
<Markdown>{roadmap.description}</Markdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-6">
|
||||
<p className="text-sm text-secondary">
|
||||
Have opinions about what we should build next?{' '}
|
||||
<Link to="/roadmap" className="text-primary underline" state={{ newWindow: true }}>
|
||||
Vote on our roadmap.
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -2,28 +2,14 @@ import React from 'react'
|
||||
import { useStaticQuery, graphql, Link } from 'gatsby'
|
||||
import { createSlideConfig, SlidesTemplate } from 'components/Products/Slides'
|
||||
import { useContentData } from 'hooks/useContentData'
|
||||
import { useRoadmaps } from 'hooks/useRoadmaps'
|
||||
import Markdown from 'components/Squeak/components/Markdown'
|
||||
import { IconCheck, IconLightBulb } from '@posthog/icons'
|
||||
import { IconLightBulb } from '@posthog/icons'
|
||||
import Cards from 'components/Cards'
|
||||
import { PostHogAIExampleCards } from 'components/Cards/data'
|
||||
import ScrollArea from 'components/RadixUI/ScrollArea'
|
||||
import CustomRoadmapSlide from 'components/AI/CustomRoadmapSlide'
|
||||
|
||||
const PRODUCT_HANDLE = 'posthog_ai'
|
||||
|
||||
interface RoadmapItem {
|
||||
id: string
|
||||
attributes: {
|
||||
title: string
|
||||
description: string
|
||||
projectedCompletion?: string
|
||||
complete?: boolean
|
||||
likes: {
|
||||
data: Array<{ id: string }>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CustomManifestoSlide = () => {
|
||||
return (
|
||||
<div
|
||||
@@ -80,134 +66,6 @@ const CustomManifestoSlide = () => {
|
||||
)
|
||||
}
|
||||
|
||||
const CustomRoadmapSlide = () => {
|
||||
const { roadmaps, isLoading } = useRoadmaps({
|
||||
params: {
|
||||
filters: {
|
||||
$or: [
|
||||
{
|
||||
teams: {
|
||||
name: {
|
||||
$eq: 'PostHog AI',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div data-scheme="primary" className="flex items-center justify-center h-full bg-primary">
|
||||
<div className="text-primary">Loading roadmap...</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const underConsideration = roadmaps.filter(
|
||||
(roadmap: RoadmapItem) => !roadmap.attributes.projectedCompletion && !roadmap.attributes.complete
|
||||
)
|
||||
const inProgress = roadmaps.filter(
|
||||
(roadmap: RoadmapItem) => roadmap.attributes.projectedCompletion && !roadmap.attributes.complete
|
||||
)
|
||||
const shipped = roadmaps.filter((roadmap: RoadmapItem) => roadmap.attributes.complete)
|
||||
|
||||
return (
|
||||
<div data-scheme="primary" className="h-full bg-primary text-primary p-4 @md:p-8 overflow-auto">
|
||||
<h2 className="text-3xl @md:text-4xl font-bold mb-6 text-center">Roadmap</h2>
|
||||
|
||||
<div className="grid @lg:grid-cols-3 gap-4 max-w-7xl mx-auto">
|
||||
{/* Under Consideration */}
|
||||
<div className="border border-primary rounded overflow-hidden">
|
||||
<h3 className="text-sm @md:text-base text-center bg-accent px-4 py-2 mb-0 font-semibold">
|
||||
Under consideration
|
||||
</h3>
|
||||
<div className="divide-y divide-primary overflow-y-auto">
|
||||
{underConsideration.slice(0, 3).map((roadmap: RoadmapItem) => (
|
||||
<div key={roadmap.id} className="p-3">
|
||||
<div className="flex gap-2">
|
||||
<div className="shrink-0">
|
||||
<div className="bg-[#F5E2B2] rounded px-2 py-1 text-xs font-semibold">
|
||||
{roadmap.attributes.likes.data.length}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="text-sm font-bold mb-1 leading-tight truncate">
|
||||
{roadmap.attributes.title}
|
||||
</h4>
|
||||
<div className="text-xs line-clamp-2">
|
||||
<Markdown>{roadmap.attributes.description}</Markdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* In Progress */}
|
||||
<div className="border border-primary rounded overflow-hidden">
|
||||
<h3 className="text-sm @md:text-base text-center bg-orange text-white px-4 py-2 mb-0 font-semibold">
|
||||
In progress
|
||||
</h3>
|
||||
<div className="divide-y divide-primary overflow-y-auto">
|
||||
{inProgress.slice(0, 3).map((roadmap: RoadmapItem) => (
|
||||
<div key={roadmap.id} className="p-3">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="text-sm font-bold mb-1 leading-tight truncate">
|
||||
{roadmap.attributes.title}
|
||||
</h4>
|
||||
<div className="text-xs line-clamp-2">
|
||||
<Markdown>{roadmap.attributes.description}</Markdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Shipped */}
|
||||
<div className="border border-primary rounded overflow-hidden">
|
||||
<h3 className="text-sm @md:text-base text-center bg-green px-4 py-2 mb-0 font-semibold text-white">
|
||||
Shipped
|
||||
</h3>
|
||||
<div className="divide-y divide-primary overflow-y-auto">
|
||||
{shipped.slice(0, 3).map((roadmap: RoadmapItem) => (
|
||||
<div key={roadmap.id} className="p-3">
|
||||
<div className="flex gap-2">
|
||||
<div className="shrink-0">
|
||||
<IconCheck className="w-4 h-4 text-green" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<h4 className="text-sm font-bold mb-1 leading-tight">
|
||||
{roadmap.attributes.title}
|
||||
</h4>
|
||||
<div className="text-xs line-clamp-2">
|
||||
<Markdown>{roadmap.attributes.description}</Markdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-6">
|
||||
<p className="text-sm text-secondary">
|
||||
Have opinions about what we should build next?{' '}
|
||||
<Link to="/roadmap" className="text-primary underline" state={{ newWindow: true }}>
|
||||
Vote on our roadmap.
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const CustomPricingSlide = () => {
|
||||
return (
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user