Add teams banner

pull/4554/head
Kamran Ahmed 1 year ago
parent 90f3ffe270
commit e5e0a7c8c5
  1. BIN
      public/images/team-promo/hero-img.png
  2. 17
      src/components/HeroSection/EmptyProgress.tsx
  3. 7
      src/components/HeroSection/FavoriteRoadmaps.tsx
  4. 4
      src/components/HeroSection/HeroRoadmaps.tsx
  5. 14
      src/components/HeroSection/HeroSection.astro
  6. 1
      src/components/Navigation/Navigation.astro
  7. 16
      src/components/TeamAnnouncement.tsx
  8. 11
      src/components/TeamMarketing/TeamDemo.tsx
  9. 24
      src/components/TeamMarketing/TeamHeroBanner.tsx
  10. 9
      src/components/TeamMarketing/TeamPricing.tsx

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 33 KiB

@ -1,4 +1,5 @@
import { CheckIcon } from '../ReactIcons/CheckIcon'; import { CheckIcon } from '../ReactIcons/CheckIcon';
import { TeamAnnouncement } from '../TeamAnnouncement';
type EmptyProgressProps = { type EmptyProgressProps = {
title?: string; title?: string;
@ -12,12 +13,18 @@ export function EmptyProgress(props: EmptyProgressProps) {
} = props; } = props;
return ( return (
<div className="relative flex min-h-full flex-col items-start sm:items-center justify-center py-6"> <div className="relative flex min-h-full flex-col items-start justify-center py-6 sm:items-center">
<h2 className={'mb-1 flex items-center text-lg sm:text-2xl text-gray-200'}> <h2
<CheckIcon additionalClasses='mr-2 top-[0.5px] w-[16px] h-[16px] sm:w-[20px] sm:h-[20px]' /> className={'mb-1.5 flex items-center text-lg text-gray-200 sm:text-2xl'}
Start learning .. >
<CheckIcon additionalClasses="mr-2 top-[0.5px] w-[16px] h-[16px] sm:w-[20px] sm:h-[20px]" />
{title}
</h2> </h2>
<p className={'text-gray-400 text-sm sm:text-base'}>{message}</p> <p className={'text-sm text-gray-400 sm:text-base'}>{message}</p>
<p className="mt-5">
<TeamAnnouncement />
</p>
</div> </div>
); );
} }

@ -119,7 +119,10 @@ export function FavoriteRoadmaps() {
return ( return (
<div <div
className={`flex min-h-[192px] bg-gradient-to-b transition-opacity duration-500 sm:min-h-[280px] opacity-${containerOpacity} ${ className={`transition-opacity duration-500 opacity-${containerOpacity}`}
>
<div
className={`flex min-h-[192px] bg-gradient-to-b sm:min-h-[280px] ${
hasProgress && `border-t border-t-[#1e293c]` hasProgress && `border-t border-t-[#1e293c]`
}`} }`}
> >
@ -127,7 +130,6 @@ export function FavoriteRoadmaps() {
{!isLoading && progress?.length == 0 && <EmptyProgress />} {!isLoading && progress?.length == 0 && <EmptyProgress />}
{hasProgress && ( {hasProgress && (
<HeroRoadmaps <HeroRoadmaps
showCustomRoadmaps={true}
customRoadmaps={customRoadmaps} customRoadmaps={customRoadmaps}
progress={defaultRoadmaps} progress={defaultRoadmaps}
isLoading={isLoading} isLoading={isLoading}
@ -135,5 +137,6 @@ export function FavoriteRoadmaps() {
)} )}
</div> </div>
</div> </div>
</div>
); );
} }

@ -7,6 +7,7 @@ import { MapIcon } from 'lucide-react';
import { CreateRoadmapButton } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapButton'; import { CreateRoadmapButton } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapButton';
import { CreateRoadmapModal } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal'; import { CreateRoadmapModal } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal';
import { useState } from 'react'; import { useState } from 'react';
import { TeamAnnouncement } from '../TeamAnnouncement';
type ProgressRoadmapProps = { type ProgressRoadmapProps = {
url: string; url: string;
@ -87,6 +88,9 @@ export function HeroRoadmaps(props: ProgressListProps) {
return ( return (
<div className="relative pb-12 pt-4 sm:pt-7"> <div className="relative pb-12 pt-4 sm:pt-7">
<p className="mb-7 text-sm mt-2">
<TeamAnnouncement />
</p>
{isCreatingRoadmap && ( {isCreatingRoadmap && (
<CreateRoadmapModal onClose={() => setIsCreatingRoadmap(false)} /> <CreateRoadmapModal onClose={() => setIsCreatingRoadmap(false)} />
)} )}

@ -1,23 +1,17 @@
--- ---
import { FavoriteRoadmaps } from './FavoriteRoadmaps'; import { FavoriteRoadmaps } from './FavoriteRoadmaps';
import {TeamAnnouncement} from "../TeamAnnouncement";
--- ---
<div <div
class='min-h-auto relative min-h-[192px] border-b border-b-[#1e293c] sm:min-h-[281px]' class='min-h-auto relative min-h-[192px] border-b border-b-[#1e293c] sm:min-h-[281px] transition-all'
> >
<div <div
class='container px-5 py-6 pb-14 text-left transition-opacity duration-300 sm:px-0 sm:py-20 sm:text-center' class='container px-5 py-6 pb-14 text-left transition-opacity duration-300 sm:px-0 sm:py-20 sm:text-center'
id='hero-text' id='hero-text'
> >
<p class='-mt-4 sm:-mt-10 mb-4 text-gray-300'> <p class='-mt-4 sm:-mt-10 mb-7'>
<a href='/teams' class="hover:text-white"> <TeamAnnouncement />
<span
class='mr-1 rounded-sm border-black bg-white px-1 py-0.5 text-center text-xs font-semibold uppercase text-black group-hover:bg-white'
>New</span
>
<span class="hidden sm:inline ml-1">Announcing roadmaps for teams.</span>
<span class="inline-block sm:hidden ml-1">Roadmaps for teams.</span>
</a>
</p> </p>
<h1 <h1

@ -2,7 +2,6 @@
import Icon from '../AstroIcon.astro'; import Icon from '../AstroIcon.astro';
import { AccountDropdown } from './AccountDropdown'; import { AccountDropdown } from './AccountDropdown';
--- ---
<div class='bg-slate-900 py-5 text-white sm:py-8'> <div class='bg-slate-900 py-5 text-white sm:py-8'>
<nav class='container flex items-center justify-between'> <nav class='container flex items-center justify-between'>
<a <a

@ -0,0 +1,16 @@
type TeamAnnouncementProps = {};
export function TeamAnnouncement(props: TeamAnnouncementProps) {
return (
<a
className="rounded-md border border-dashed border-purple-700 px-3 py-1.5 text-purple-400 transition-colors hover:border-gray-700 hover:text-white"
href="/teams"
>
<span className="relative -top-[0.5px] mr-1 text-xs font-semibold uppercase text-white">
New
</span>{' '}
<span className={'hidden sm:inline'}>Announcing roadmaps for teams. <span className='font-semibold'>Learn more!</span></span>
<span className={'inline sm:hidden'}>Announcing roadmaps for teams!</span>
</a>
);
}

@ -1,6 +1,7 @@
import { useState } from 'react'; import { useEffect, useState } from 'react';
import { cn } from '../../lib/classname.ts'; import { cn } from '../../lib/classname.ts';
import { isLoggedIn } from '../../lib/jwt.ts'; import { isLoggedIn } from '../../lib/jwt.ts';
import { fireTeamCreationClick } from './TeamHeroBanner.tsx';
const demoItems = [ const demoItems = [
{ {
@ -56,7 +57,11 @@ export function TeamDemo() {
const [hasViewed, setHasViewed] = useState<number[]>([0]); const [hasViewed, setHasViewed] = useState<number[]>([0]);
const [activeItem, setActiveItem] = useState(demoItems[0]); const [activeItem, setActiveItem] = useState(demoItems[0]);
const isAuthenticated = isLoggedIn(); const [isAuthenticated, setIsAuthenticated] = useState<boolean>();
useEffect(() => {
setIsAuthenticated(isLoggedIn());
}, []);
return ( return (
<div className="hidden border-t py-12 sm:block"> <div className="hidden border-t py-12 sm:block">
@ -122,6 +127,7 @@ export function TeamDemo() {
<div className="flex flex-row items-center gap-2"> <div className="flex flex-row items-center gap-2">
<a <a
onClick={() => { onClick={() => {
fireTeamCreationClick();
if (isAuthenticated) { if (isAuthenticated) {
return; return;
} }
@ -138,6 +144,7 @@ export function TeamDemo() {
or &nbsp; or &nbsp;
<a <a
onClick={() => { onClick={() => {
fireTeamCreationClick();
localStorage.setItem('authRedirect', '/team/new'); localStorage.setItem('authRedirect', '/team/new');
}} }}
href="/login" href="/login"

@ -1,5 +1,6 @@
import { CheckCircle, CheckCircle2, CheckIcon } from 'lucide-react'; import { CheckCircle, CheckCircle2, CheckIcon } from 'lucide-react';
import { isLoggedIn } from '../../lib/jwt.ts'; import { isLoggedIn } from '../../lib/jwt.ts';
import { useEffect, useState } from 'react';
const featureList = [ const featureList = [
'Create custom roadmaps for your team', 'Create custom roadmaps for your team',
@ -8,8 +9,21 @@ const featureList = [
"Get insights on your team's skills and growth", "Get insights on your team's skills and growth",
]; ];
export function fireTeamCreationClick() {
window.fireEvent({
category: 'FeatureClick',
action: `Pages / Teams`,
label: 'Create your Team',
});
}
export function TeamHeroBanner() { export function TeamHeroBanner() {
const isAuthenticated = isLoggedIn(); const [isAuthenticated, setIsAuthenticated] = useState<boolean>();
useEffect(() => {
setIsAuthenticated(isLoggedIn());
}, []);
return ( return (
<div className="bg-white py-8 lg:py-12"> <div className="bg-white py-8 lg:py-12">
<div className="container"> <div className="container">
@ -34,11 +48,7 @@ export function TeamHeroBanner() {
<div className="flex flex-col items-start gap-2 sm:flex-row sm:items-center"> <div className="flex flex-col items-start gap-2 sm:flex-row sm:items-center">
<a <a
onClick={() => { onClick={() => {
if (isAuthenticated) { fireTeamCreationClick();
return;
}
localStorage.setItem('authRedirect', '/team/new');
}} }}
href={isAuthenticated ? '/team/new' : '/signup'} href={isAuthenticated ? '/team/new' : '/signup'}
className="flex w-full items-center justify-center rounded-lg border border-transparent bg-purple-600 px-5 py-2 text-sm font-medium text-white hover:bg-blue-700 sm:w-auto sm:text-base" className="flex w-full items-center justify-center rounded-lg border border-transparent bg-purple-600 px-5 py-2 text-sm font-medium text-white hover:bg-blue-700 sm:w-auto sm:text-base"
@ -52,6 +62,7 @@ export function TeamHeroBanner() {
<a <a
href="/login" href="/login"
onClick={() => { onClick={() => {
fireTeamCreationClick();
localStorage.setItem('authRedirect', '/team/new'); localStorage.setItem('authRedirect', '/team/new');
}} }}
className="text-purple-600 underline hover:text-purple-700" className="text-purple-600 underline hover:text-purple-700"
@ -62,6 +73,7 @@ export function TeamHeroBanner() {
<a <a
href="/login" href="/login"
onClick={() => { onClick={() => {
fireTeamCreationClick();
localStorage.setItem('authRedirect', '/team/new'); localStorage.setItem('authRedirect', '/team/new');
}} }}
className="flex w-full items-center justify-center rounded-lg border border-purple-600 px-5 py-2 text-base text-sm font-medium text-purple-600 hover:bg-blue-700 sm:hidden sm:text-base" className="flex w-full items-center justify-center rounded-lg border border-purple-600 px-5 py-2 text-base text-sm font-medium text-purple-600 hover:bg-blue-700 sm:hidden sm:text-base"

@ -2,12 +2,18 @@ import { Check, CheckCircle, Copy, Sparkles } from 'lucide-react';
import { useCopyText } from '../../hooks/use-copy-text.ts'; import { useCopyText } from '../../hooks/use-copy-text.ts';
import { cn } from '../../lib/classname.ts'; import { cn } from '../../lib/classname.ts';
import { isLoggedIn } from '../../lib/jwt.ts'; import { isLoggedIn } from '../../lib/jwt.ts';
import { fireTeamCreationClick } from './TeamHeroBanner.tsx';
import { useEffect, useState } from 'react';
export function TeamPricing() { export function TeamPricing() {
const { isCopied, copyText } = useCopyText(); const { isCopied, copyText } = useCopyText();
const teamEmail = 'teams@roadmap.sh'; const teamEmail = 'teams@roadmap.sh';
const isAuthenticated = isLoggedIn(); const [isAuthenticated, setIsAuthenticated] = useState<boolean>();
useEffect(() => {
setIsAuthenticated(isLoggedIn());
}, []);
return ( return (
<div className="border-t py-4 sm:py-8 md:py-12"> <div className="border-t py-4 sm:py-8 md:py-12">
@ -32,6 +38,7 @@ export function TeamPricing() {
<a <a
onClick={() => { onClick={() => {
fireTeamCreationClick();
if (isAuthenticated) { if (isAuthenticated) {
return; return;
} }

Loading…
Cancel
Save