diff --git a/apps/web/src/routes/_view/product/mini-apps.tsx b/apps/web/src/routes/_view/product/mini-apps.tsx index 2a8a8ac483..3b3a296e13 100644 --- a/apps/web/src/routes/_view/product/mini-apps.tsx +++ b/apps/web/src/routes/_view/product/mini-apps.tsx @@ -1,6 +1,7 @@ import { Icon } from "@iconify-icon/react"; import { createFileRoute } from "@tanstack/react-router"; -import { useState } from "react"; +import { CheckIcon } from "lucide-react"; +import { useEffect, useRef, useState } from "react"; import { cn } from "@hypr/utils"; @@ -35,7 +36,7 @@ function Component() { - + @@ -74,174 +75,50 @@ function HeroSection() { } function ContactsSection() { + const [currentImage, setCurrentImage] = useState(0); + + const images = [ + "/api/images/hyprnote/mini-apps/contacts-human.jpg", + "/api/images/hyprnote/mini-apps/contacts-org.jpg", + ]; + + useEffect(() => { + const interval = setInterval(() => { + setCurrentImage((prev) => (prev + 1) % images.length); + }, 4000); + + return () => clearInterval(interval); + }, [images.length]); + return (
-
-
-
-

Contacts

-

- Track who you meet with and what you discuss. Never forget a - conversation. +

+
+
+

+ Contacts +

+

+ A relationship-focused CRM that builds itself from your meetings. + Import contacts and watch them come alive with context once you + actually meet.

-
    -
  • - - - Auto-detected contacts from meetings - -
  • -
  • - - - Conversation timeline and history - -
  • -
  • - - - Topic tracking and context - -
  • -
-
-
-
-
-
- -
-
-

- Sarah Johnson -

-

- Product Manager at Acme Inc -

-
- - - 12 meetings - - - - Last met: 2 days ago - -
-
-
-
-
-
- Recent Topics -
-
- - Q1 Planning - - - Mobile App - - - User Research - -
-
-
-
-
-
-
-
-

Contacts

-

- Track who you meet with and what you discuss. Never forget a - conversation. -

-
    -
  • - - - Auto-detected contacts from meetings - -
  • -
  • - - - Conversation timeline and history - -
  • -
  • - + {images.map((image, index) => ( + Contacts interface - - Topic tracking and context - -
  • -
-
-
-
-
-
- -
-
-

- Sarah Johnson -

-

- Product Manager at Acme Inc -

-
- - - 12 meetings - - - - Last met: 2 days ago - -
-
-
-
-
-
- Recent Topics -
-
- - Q1 Planning - - - Mobile App - - - User Research - -
-
-
+ ))}
@@ -262,28 +139,19 @@ function CalendarSection() {

  • - + Automatic meeting linking
  • - + Pre-meeting context and preparation
  • - + Timeline view with notes @@ -339,28 +207,19 @@ function CalendarSection() {

    • - + Automatic meeting linking
    • - + Pre-meeting context and preparation
    • - + Timeline view with notes @@ -422,31 +281,31 @@ function DailyNotesSection() {

      • - + Automatic aggregation of meetings + + Coming soon +
      • - + Chronological timeline view + + Coming soon +
      • - + AI-generated daily summary + + Coming soon +
@@ -469,31 +328,31 @@ function DailyNotesSection() {

  • - + Automatic aggregation of meetings + + Coming soon +
  • - + Chronological timeline view + + Coming soon +
  • - + AI-generated daily summary + + Coming soon +
@@ -507,124 +366,157 @@ function DailyNotesSection() { ); } -function NoteshelfSection() { +function FoldersSection() { return ( -
+
-

Noteshelf

+

Folders

- Your workspace for notes, ideas, and reflections alongside your - meetings. + Organize your meetings and notes into folders for easy access and + better structure.

  • - + - Personal notes and reflections + Group related meetings together
  • - - Link notes to meetings + + + Organize by project, client, or topic +
  • - + - Full-text search across all notes + Quick navigation and filtering
-
-
-

Coming soon

-
+
+ Folders interface
-

Noteshelf

+

Folders

- Your workspace for notes, ideas, and reflections alongside your - meetings. + Organize your meetings and notes into folders for easy access and + better structure.

  • - + - Personal notes and reflections + Group related meetings together
  • - + - Link notes to meetings + Organize by project, client, or topic
  • - + - Full-text search across all notes + Quick navigation and filtering
-
-
-

Coming soon

-
+
+ Folders interface
); } +const ADVANCED_SEARCH_AUTO_ADVANCE_DURATION = 5000; + +const advancedSearchImages = [ + { + id: 1, + url: "/api/images/hyprnote/mini-apps/search-default.jpg", + title: "Suggestions", + description: + "Get instant search result suggestions based on recent activities", + }, + { + id: 2, + url: "/api/images/hyprnote/mini-apps/search-semantic.jpg", + title: "Semantic search", + description: "Find relevant info even without exact keywords", + }, + { + id: 3, + url: "/api/images/hyprnote/mini-apps/search-filter.jpg", + title: "Filters", + description: "Filter out result types easily", + }, +]; + function AdvancedSearchSection() { const [selectedImage, setSelectedImage] = useState(1); + const [progress, setProgress] = useState(0); + const [isPaused, setIsPaused] = useState(false); + const progressRef = useRef(0); - const images = [ - { - id: 1, - url: "/api/images/hyprnote/search-1.jpg", - title: "Suggestions", - description: - "Get instant search result suggestions based on recent activities", - }, - { - id: 2, - url: "/api/images/hyprnote/search-2.jpg", - title: "Semantic search", - description: "Find relevant info even without exact keywords", - }, - { - id: 3, - url: "/api/images/hyprnote/search-3.jpg", - title: "Filters", - description: "Filter out result types easily", - }, - ]; + useEffect(() => { + if (isPaused) return; + + const startTime = + Date.now() - + (progressRef.current / 100) * ADVANCED_SEARCH_AUTO_ADVANCE_DURATION; + let animationId: number; + + const animate = () => { + const elapsed = Date.now() - startTime; + const newProgress = Math.min( + (elapsed / ADVANCED_SEARCH_AUTO_ADVANCE_DURATION) * 100, + 100, + ); + setProgress(newProgress); + progressRef.current = newProgress; + + if (newProgress >= 100) { + const currentIndex = advancedSearchImages.findIndex( + (img) => img.id === selectedImage, + ); + const nextIndex = (currentIndex + 1) % advancedSearchImages.length; + setSelectedImage(advancedSearchImages[nextIndex].id); + setProgress(0); + progressRef.current = 0; + } else { + animationId = requestAnimationFrame(animate); + } + }; + + animationId = requestAnimationFrame(animate); + return () => cancelAnimationFrame(animationId); + }, [selectedImage, isPaused]); + + const handleTabClick = (imageId: number) => { + setSelectedImage(imageId); + setProgress(0); + progressRef.current = 0; + }; return (
- {images.map((image, index) => ( + {advancedSearchImages.map((image, index) => (