From f29a27f5a0d5fc6b2335b9e6ea320f06c5262a9e Mon Sep 17 00:00:00 2001 From: Radhika Bacharwar Date: Sun, 23 Jun 2024 12:39:30 +0530 Subject: [PATCH] webinar section --- package-lock.json | 15 +++ package.json | 2 + src/app/page.tsx | 4 + src/components/FeaturedCourses.tsx | 56 +++++---- src/components/MusicSchoolTestimonial.tsx | 56 +++++++++ src/components/UpcomingWebinars.tsx | 87 ++++++++++++++ src/components/ui/card-hover-effect.tsx | 111 ++++++++++++++++++ src/components/ui/infinite-moving-cards.tsx | 121 ++++++++++++++++++++ tailwind.config.ts | 35 +++++- 9 files changed, 461 insertions(+), 26 deletions(-) create mode 100644 src/components/MusicSchoolTestimonial.tsx create mode 100644 src/components/UpcomingWebinars.tsx create mode 100644 src/components/ui/card-hover-effect.tsx create mode 100644 src/components/ui/infinite-moving-cards.tsx diff --git a/package-lock.json b/package-lock.json index 16ed310..a4a46cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,11 @@ "dependencies": { "clsx": "^2.1.1", "framer-motion": "^11.2.11", + "mini-svg-data-uri": "^1.4.4", "next": "14.2.4", "react": "^18", "react-dom": "^18", + "simplex-noise": "^4.0.1", "tailwind-merge": "^2.3.0" }, "devDependencies": { @@ -3078,6 +3080,14 @@ "node": ">=8.6" } }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4072,6 +4082,11 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simplex-noise": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simplex-noise/-/simplex-noise-4.0.1.tgz", + "integrity": "sha512-zl/+bdSqW7HJOQ0oDbxrNYaF4F5ik0i7M6YOYmEoIJNtg16NpvWaTTM1Y7oV/7T0jFljawLgYPS81Uu2rsfo1A==" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", diff --git a/package.json b/package.json index 3339bcc..deb60f1 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,11 @@ "dependencies": { "clsx": "^2.1.1", "framer-motion": "^11.2.11", + "mini-svg-data-uri": "^1.4.4", "next": "14.2.4", "react": "^18", "react-dom": "^18", + "simplex-noise": "^4.0.1", "tailwind-merge": "^2.3.0" }, "devDependencies": { diff --git a/src/app/page.tsx b/src/app/page.tsx index e402672..5b8edc3 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,5 +1,7 @@ import FeaturedCourses from "@/components/FeaturedCourses"; import HeroSection from "@/components/HeroSection"; +import MusicSchoolTestimonial from "@/components/MusicSchoolTestimonial"; +import UpcomingWebinars from "@/components/UpcomingWebinars"; import WhyChooseUs from "@/components/WhyChooseUs"; export default function Home() { @@ -8,6 +10,8 @@ export default function Home() { < HeroSection/> < FeaturedCourses/> < WhyChooseUs /> + + < UpcomingWebinars/> ); } diff --git a/src/components/FeaturedCourses.tsx b/src/components/FeaturedCourses.tsx index fb72ca4..d279bcf 100644 --- a/src/components/FeaturedCourses.tsx +++ b/src/components/FeaturedCourses.tsx @@ -31,32 +31,38 @@ function FeaturedCourses() { Learn With the Best

- -
-
- {featuredCourses.map((course: Course) => ( -
- -
-

{course.title}

-

{course.description}

- - Learn More - -
-
-
- ))} +
+
+ {featuredCourses.map((course: Course) => ( +
+ +
+

+ {course.title} +

+

+ {course.description} +

+ + Learn More + +
+
+
+ ))} +
+
+
+ + View All courses +
-
-
- - View All courses -
); diff --git a/src/components/MusicSchoolTestimonial.tsx b/src/components/MusicSchoolTestimonial.tsx new file mode 100644 index 0000000..82fddf8 --- /dev/null +++ b/src/components/MusicSchoolTestimonial.tsx @@ -0,0 +1,56 @@ +'use client' +import { InfiniteMovingCards } from "./ui/infinite-moving-cards"; + +const musicSchoolTestimonials=[ + { + quote: + 'Joining the music school transformed my understanding of music and helped me to truly discover my own sound. The instructors are world-class!', + name: 'Alex Johnson', + title: 'Guitar Student', + }, + { + quote: + "The community and support at this school are unmatched. I've grown not just as a pianist, but also as a performer, thanks to their comprehensive approach.", + name: 'Samantha Lee', + title: 'Piano Student', + }, + { + quote: + "This school offered me the tools and confidence to take my singing to the next level. I'm endlessly grateful for the personalized coaching.", + name: 'Michael Chen', + title: 'Vocal Student', + }, + { + quote: + 'As a violinist, finding the right mentor can be challenging, but this school matched me with a teacher who truly understands my goals and challenges.', + name: 'Emily Taylor', + title: 'Violin Student', + }, + { + quote: + 'The production courses here opened my eyes to the intricacies of music production. Highly recommend for any aspiring producers!', + name: 'Chris Morales', + title: 'Music Production Student', + }, +]; +function MusicSchoolTestimonial() { + + + return ( +
+

Hear our Harmony: Voies of Success

+
+
+ +
+ +
+
+ ) +} + +export default MusicSchoolTestimonial diff --git a/src/components/UpcomingWebinars.tsx b/src/components/UpcomingWebinars.tsx new file mode 100644 index 0000000..643620e --- /dev/null +++ b/src/components/UpcomingWebinars.tsx @@ -0,0 +1,87 @@ +"use client"; + +import Link from "next/link"; +import { HoverEffect } from "./ui/card-hover-effect"; + +function UpcomingWebinars() { + const featuredWebinars = [ + { + title: 'Understanding Music Theory', + description: + 'Dive deep into the fundamentals of music theory and enhance your musical skills.', + slug: 'understanding-music-theory', + isFeatured: true, + }, + { + title: 'The Art of Songwriting', + description: + 'Learn the craft of songwriting from experienced musicians and songwriters.', + slug: 'the-art-of-songwriting', + isFeatured: true, + }, + { + title: 'Mastering Your Instrument', + description: + 'Advanced techniques to master your musical instrument of choice.', + slug: 'mastering-your-instrument', + isFeatured: true, + }, + { + title: 'Music Production Essentials', + description: + 'Get started with music production with this comprehensive overview.', + slug: 'music-production-essentials', + isFeatured: true, + }, + // Added two more webinars + { + title: 'Live Performance Techniques', + description: + 'Enhance your live performance skills with expert tips and strategies.', + slug: 'live-performance-techniques', + isFeatured: true, + }, + { + title: 'Digital Music Marketing', + description: + 'Learn how to promote your music effectively in the digital age.', + slug: 'digital-music-marketing', + isFeatured: true, + }, + ]; + return ( +
+
+
+

+ FEATURED WEBINARS +

+

+ Enhance Your Musical Journey +

+
+ +
+ ({ + title: webinar.title, + description:webinar.description, + link:'/' + } + ))} + /> +
+
+ + View All webinars + +
+
+
+ ); +} + +export default UpcomingWebinars; diff --git a/src/components/ui/card-hover-effect.tsx b/src/components/ui/card-hover-effect.tsx new file mode 100644 index 0000000..cc3283c --- /dev/null +++ b/src/components/ui/card-hover-effect.tsx @@ -0,0 +1,111 @@ +import { cn } from "@/utils/cn"; +import { AnimatePresence, motion } from "framer-motion"; +import Link from "next/link"; +import { useState } from "react"; + +export const HoverEffect = ({ + items, + className, +}: { + items: { + title: string; + description: string; + link: string; + }[]; + className?: string; +}) => { + let [hoveredIndex, setHoveredIndex] = useState(null); + + return ( +
+ {items.map((item, idx) => ( + setHoveredIndex(idx)} + onMouseLeave={() => setHoveredIndex(null)} + > + + {hoveredIndex === idx && ( + + )} + + + {item.title} + {item.description} + + + ))} +
+ ); +}; + +export const Card = ({ + className, + children, +}: { + className?: string; + children: React.ReactNode; +}) => { + return ( +
+
+
{children}
+
+
+ ); +}; +export const CardTitle = ({ + className, + children, +}: { + className?: string; + children: React.ReactNode; +}) => { + return ( +

+ {children} +

+ ); +}; +export const CardDescription = ({ + className, + children, +}: { + className?: string; + children: React.ReactNode; +}) => { + return ( +

+ {children} +

+ ); +}; diff --git a/src/components/ui/infinite-moving-cards.tsx b/src/components/ui/infinite-moving-cards.tsx new file mode 100644 index 0000000..d782004 --- /dev/null +++ b/src/components/ui/infinite-moving-cards.tsx @@ -0,0 +1,121 @@ +"use client"; + +import { cn } from "@/utils/cn"; +import React, { useEffect, useState } from "react"; + +export const InfiniteMovingCards = ({ + items, + direction = "left", + speed = "fast", + pauseOnHover = true, + className, +}: { + items: { + quote: string; + name: string; + title: string; + }[]; + direction?: "left" | "right"; + speed?: "fast" | "normal" | "slow"; + pauseOnHover?: boolean; + className?: string; +}) => { + const containerRef = React.useRef(null); + const scrollerRef = React.useRef(null); + + useEffect(() => { + addAnimation(); + }, []); + const [start, setStart] = useState(false); + function addAnimation() { + if (containerRef.current && scrollerRef.current) { + const scrollerContent = Array.from(scrollerRef.current.children); + + scrollerContent.forEach((item) => { + const duplicatedItem = item.cloneNode(true); + if (scrollerRef.current) { + scrollerRef.current.appendChild(duplicatedItem); + } + }); + + getDirection(); + getSpeed(); + setStart(true); + } + } + const getDirection = () => { + if (containerRef.current) { + if (direction === "left") { + containerRef.current.style.setProperty( + "--animation-direction", + "forwards" + ); + } else { + containerRef.current.style.setProperty( + "--animation-direction", + "reverse" + ); + } + } + }; + const getSpeed = () => { + if (containerRef.current) { + if (speed === "fast") { + containerRef.current.style.setProperty("--animation-duration", "20s"); + } else if (speed === "normal") { + containerRef.current.style.setProperty("--animation-duration", "40s"); + } else { + containerRef.current.style.setProperty("--animation-duration", "80s"); + } + } + }; + return ( +
+
    + {items.map((item, idx) => ( +
  • +
    + + + {item.quote} + +
    + + + {item.name} + + + {item.title} + + +
    +
    +
  • + ))} +
+
+ ); +}; diff --git a/tailwind.config.ts b/tailwind.config.ts index 635c96c..74ff6bb 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -3,9 +3,10 @@ const colors = require("tailwindcss/colors"); const { default: flattenColorPalette, } = require("tailwindcss/lib/util/flattenColorPalette"); -import type { Config } from "tailwindcss"; +const svgToDataUri = require("mini-svg-data-uri"); +import type { Config } from "tailwindcss"; const config: Config = { content: [ @@ -20,7 +21,11 @@ const config: Config = { extend: { animation: { spotlight: "spotlight 2s ease .75s 1 forwards", + scroll: + "scroll var(--animation-duration, 40s) var(--animation-direction, forwards) linear infinite", + }, + backgroundImage: { "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", "gradient-conic": @@ -37,12 +42,18 @@ const config: Config = { transform: "translate(-50%,-40%) scale(1)", }, }, + scroll: { + to: { + transform: "translate(calc(-50% - 0.5rem))", + }, + }, }, }, }, plugins: [ addVariablesForColors, + addSvgPatterns, ], }; @@ -57,4 +68,26 @@ function addVariablesForColors({ addBase, theme }: any) { }); } +function addSvgPatterns({ matchUtilities, theme }: any){ + matchUtilities( + { + 'bg-grid': (value: any) => ({ + backgroundImage: `url("${svgToDataUri( + `` + )}")`, + }), + 'bg-grid-small': (value: any) => ({ + backgroundImage: `url("${svgToDataUri( + `` + )}")`, + }), + 'bg-dot': (value: any) => ({ + backgroundImage: `url("${svgToDataUri( + `` + )}")`, + }), + }, + { values: flattenColorPalette(theme('backgroundColor')), type: 'color' } + ); +} export default config;