Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"clsx": "^2.1.1",
"focus-visible": "^5.2.0",
"framer-motion": "^11.2.4",
"i18next": "^21.8.10",
"lucide-react": "^0.378.0",
"mantine-flagpack": "^4.0.1",
"next": "14.2.3",
Expand All @@ -50,6 +51,7 @@
"react-countdown": "^2.3.5",
"react-countdown-circle-timer": "^3.2.1",
"react-dom": "18.3.1",
"react-i18next": "^11.18.6",
"react-redux": "^9.1.2",
"redux": "^5.0.1",
"redux-socket.io-middleware": "^1.0.4",
Expand Down
35 changes: 33 additions & 2 deletions public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,36 @@
"title": "Welcome, streamer",
"description": "Unlock the Ultimate Dota 2 Streaming Experience with Dotabod! Boost your stream's engagement, showcase real-time stats, and delight your audience with our all-in-one streaming toolkit. Elevate your game and become the streamer you were meant to be!"
},
"live": "Live"
}
"live": "Live",
"setup": {
"title": "Setup",
"subtitle": "Let's get Dotabod working for you right away",
"step1": "Twitch",
"step2": "Dota 2",
"step3": "OBS",
"step4": "All done!",
"finalNote": "That's it! You're all set up."
},
"features": {
"main": {
"title": "Main features",
"subtitle": "Customize the options your stream receives."
},
"chat": {
"title": "Chatter",
"subtitle": "The bot can post some random messages as you play your game."
},
"advanced": {
"title": "Advanced features",
"subtitle": "Looking for even more? They'll be here 😎"
},
"overlay": {
"title": "Overlay",
"subtitle": "This stuff will show up on your stream"
}
},
"troubleshoot": {
"title": "Live preview",
"subtitle": "Take a peak to see if your OBS is showing the correct overlay. Try joining a bot match to have this preview show the pick blocker, for example."
}
}
21 changes: 10 additions & 11 deletions src/components/Homepage/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { CursorArrowRaysIcon } from '@heroicons/react/24/outline'
import useSWR from 'swr'
import { fetcher } from '@/lib/fetcher'
import TwitchSvg from 'src/images/logos/twitch.svg'
import { useTranslation } from 'react-i18next';

const featuredUsers = [
{
Expand Down Expand Up @@ -132,6 +133,7 @@ const TwitchUser = ({
}

export function Hero() {
const { t } = useTranslation();
const session = useSession()
const name = session.data?.user?.name || 'streamers'
const { nonSupporters } = grouped
Expand All @@ -147,7 +149,7 @@ export function Hero() {
<div className="lg:grid lg:grid-cols-12 lg:gap-x-8 lg:gap-y-20">
<div className="relative z-10 mx-auto max-w-2xl lg:col-span-7 lg:max-w-none lg:pt-6 xl:col-span-6">
<h1 className="flex items-center space-x-2 text-4xl font-medium tracking-tight text-gray-200">
<span>Welcome, {name}</span>
<span>{t('hero.title', 'Welcome, streamer')}</span>
<Image
src="/images/emotes/peepoclap.webp"
width={38}
Expand All @@ -156,20 +158,17 @@ export function Hero() {
/>
</h1>
<p className="mt-6 text-lg text-gray-300">
Unlock the Ultimate Dota 2 Streaming Experience with Dotabod!
Boost your stream&apos;s engagement, showcase real-time stats, and
delight your audience with our all-in-one streaming toolkit.
Elevate your game and become the streamer you were meant to be!
{t('hero.description', "Unlock the Ultimate Dota 2 Streaming Experience with Dotabod! Boost your stream's engagement, showcase real-time stats, and delight your audience with our all-in-one streaming toolkit. Elevate your game and become the streamer you were meant to be!")}
</p>
<div className="mt-8 flex flex-wrap gap-x-6 gap-y-4">
<Link href="/dashboard">
<Button type="primary">
<div className="flex items-center space-x-2">
<CursorArrowRaysIcon className="flex h-4 w-4" />
{session?.status === 'authenticated' ? (
<span>Go to dashboard</span>
<span>{t('hero.dashboard', 'Go to dashboard')}</span>
) : (
<span>Get started</span>
<span>{t('hero.getStarted', 'Get started')}</span>
)}
</div>
</Button>
Expand All @@ -181,7 +180,7 @@ export function Hero() {
>
<div className="flex items-center space-x-2">
<Image alt="discord" src={DiscordSvg} className="h-4 w-4" />
<span>Join Discord</span>
<span>{t('hero.joinDiscord', 'Join Discord')}</span>
</div>
</Button>
</div>
Expand Down Expand Up @@ -211,7 +210,7 @@ export function Hero() {
height={18}
alt="twitch logo"
/>
<span>Featured in over 15,000 Twitch streamers</span>
<span>{t('hero.featuredStreamers', 'Featured in over 15,000 Twitch streamers')}</span>
</div>
</div>
<ul className="mx-auto flex max-w-xl flex-wrap justify-center lg:mx-0 lg:justify-start">
Expand Down Expand Up @@ -241,7 +240,7 @@ export function Hero() {
<div className="relative lg:col-span-7 xl:col-span-6">
<div className="flex items-center space-x-2 text-center text-sm font-semibold text-gray-300 lg:text-left">
<LiveIcon />
<span>Top streamers using Dotabod:</span>
<span>{t('hero.topStreamers', 'Top streamers using Dotabod:')}</span>
</div>
</div>
<ul className="mx-auto flex max-w-xl flex-wrap justify-center lg:mx-0 lg:justify-start">
Expand All @@ -259,7 +258,7 @@ export function Hero() {
<div className="relative lg:col-span-7 xl:col-span-6">
<div className="flex items-center space-x-2 text-center text-sm font-semibold text-gray-300 lg:text-left">
<LiveIcon />
<span>Random Dotabod streamers:</span>
<span>{t('hero.randomStreamers', 'Random Dotabod streamers:')}</span>
</div>
</div>
<ul className="mx-auto flex max-w-xl flex-wrap justify-center lg:mx-0 lg:justify-start">
Expand Down
94 changes: 49 additions & 45 deletions src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Analytics as VercelAnalytics } from '@vercel/analytics/react'
import { SessionProvider } from 'next-auth/react'
import { I18nextProvider } from 'react-i18next';
import i18n from '../i18n';

import '@/styles/tailwind.css'
import 'focus-visible'
Expand Down Expand Up @@ -38,53 +40,55 @@ const App = ({

return (
<SessionProvider session={session}>
<ConfigProvider
theme={{
algorithm: theme.darkAlgorithm,
components: {
Button: {
colorLink: 'var(--color-purple-300)',
colorPrimaryHover: 'var(--color-purple-300)',
<I18nextProvider i18n={i18n}>
<ConfigProvider
theme={{
algorithm: theme.darkAlgorithm,
components: {
Button: {
colorLink: 'var(--color-purple-300)',
colorPrimaryHover: 'var(--color-purple-300)',
},
Tabs: {
colorPrimary: 'var(--color-purple-400)',
itemHoverColor: 'var(--color-purple-300)',
},
Menu: {
colorSubItemBg: 'var(--color-gray-800)',
colorItemBgHover: 'var(--color-gray-700)',
colorItemBgSelected: 'var(--color-gray-600)',
colorItemTextSelected: 'var(--color-gray-200)',
colorItemText: 'var(--color-gray-300)',
},
Switch: {
colorPrimary: 'var(--color-purple-900)',
},
},
Tabs: {
colorPrimary: 'var(--color-purple-400)',
itemHoverColor: 'var(--color-purple-300)',
token: {
colorPrimary: 'rgb(85, 24, 103)',
colorLink: 'var(--color-purple-500)',
colorLinkActive: 'var(--color-purple-300)',
colorLinkHover: 'var(--color-purple-300)',
colorText: 'var(--color-gray-200)',
colorBgLayout: 'var(--color-gray-900)',
colorBgContainer: 'var(--color-gray-800)',
},
Menu: {
colorSubItemBg: 'var(--color-gray-800)',
colorItemBgHover: 'var(--color-gray-700)',
colorItemBgSelected: 'var(--color-gray-600)',
colorItemTextSelected: 'var(--color-gray-200)',
colorItemText: 'var(--color-gray-300)',
},
Switch: {
colorPrimary: 'var(--color-purple-900)',
},
},
token: {
colorPrimary: 'rgb(85, 24, 103)',
colorLink: 'var(--color-purple-500)',
colorLinkActive: 'var(--color-purple-300)',
colorLinkHover: 'var(--color-purple-300)',
colorText: 'var(--color-gray-200)',
colorBgLayout: 'var(--color-gray-900)',
colorBgContainer: 'var(--color-gray-800)',
},
}}
>
<StyleProvider hashPriority="high">
<SentrySession />
<VercelAnalytics />
<GoogleAnalytics />
<MantineProvider>
<Provider store={store}>
<AntProvider>
{getLayout(<Component {...pageProps} />)}
</AntProvider>
</Provider>
</MantineProvider>
</StyleProvider>
</ConfigProvider>
}}
>
<StyleProvider hashPriority="high">
<SentrySession />
<VercelAnalytics />
<GoogleAnalytics />
<MantineProvider>
<Provider store={store}>
<AntProvider>
{getLayout(<Component {...pageProps} />)}
</AntProvider>
</Provider>
</MantineProvider>
</StyleProvider>
</ConfigProvider>
</I18nextProvider>
</SessionProvider>
)
}
Expand Down
8 changes: 5 additions & 3 deletions src/pages/dashboard/features/advanced.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ import Head from 'next/head'
import { ReactElement } from 'react'
import type { NextPageWithLayout } from '@/pages/_app'
import Header from '@/components/Dashboard/Header'
import { useTranslation } from 'react-i18next';

const FeaturesPage: NextPageWithLayout = () => {
const { status } = useSession()
const { t } = useTranslation();

return status === 'authenticated' ? (
<>
<Head>
<title>Dotabod | Advanced features</title>
<title>{t('features.advanced.title')}</title>
</Head>

<Header
subtitle="Looking for even more? They'll be here 😎"
title="Advanced features"
subtitle={t('features.advanced.subtitle')}
title={t('features.advanced.title')}
/>

<SceneSwitcher />
Expand Down
8 changes: 5 additions & 3 deletions src/pages/dashboard/features/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ import Head from 'next/head'
import { ReactElement } from 'react'
import type { NextPageWithLayout } from '@/pages/_app'
import Header from '@/components/Dashboard/Header'
import { useTranslation } from 'react-i18next';

const FeaturesPage: NextPageWithLayout = () => {
const { status } = useSession()
const { t } = useTranslation();

return status === 'authenticated' ? (
<>
<Head>
<title>Dotabod | Chat features</title>
<title>{t('features.chat.title')}</title>
</Head>

<Header
subtitle="The bot can post some random messages as you play your game."
title="Chatter"
subtitle={t('features.chat.subtitle')}
title={t('features.chat.title')}
/>

<ChatterCard />
Expand Down
8 changes: 5 additions & 3 deletions src/pages/dashboard/features/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@ import { ReactElement } from 'react'
import type { NextPageWithLayout } from '@/pages/_app'
import Header from '@/components/Dashboard/Header'
import IdeaCard from '@/components/Dashboard/Features/IdeaCard'
import { useTranslation } from 'react-i18next';

const FeaturesPage: NextPageWithLayout = () => {
const { status } = useSession()
const { t } = useTranslation();

return status === 'authenticated' ? (
<>
<Head>
<title>Dotabod | Main features</title>
<title>{t('features.main.title')}</title>
</Head>

<Header
subtitle="Customize the options your stream receives."
title="Main features"
subtitle={t('features.main.subtitle')}
title={t('features.main.title')}
/>

<div className="grid grid-cols-1 gap-6 md:grid-cols-1 lg:grid-cols-2">
Expand Down
8 changes: 5 additions & 3 deletions src/pages/dashboard/features/overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,21 @@ import QueueCard from '@/components/Dashboard/Features/QueueCard'
import MmrOverlay from '@/components/Overlay/MmrOverlay'
import BetsOverlay from '@/components/Overlay/BetsOverlay'
import WinProbabilityOverlay from '@/components/Overlay/WinProbabilityOverlay'
import { useTranslation } from 'react-i18next';

const FeaturesPage: NextPageWithLayout = () => {
const { status } = useSession()
const { t } = useTranslation();

return status === 'authenticated' ? (
<>
<Head>
<title>Dotabod | Overlay features</title>
<title>{t('features.overlay.title')}</title>
</Head>

<Header
subtitle="This stuff will show up on your stream"
title="Overlay"
subtitle={t('features.overlay.subtitle')}
title={t('features.overlay.title')}
/>

<div className="grid grid-cols-1 gap-6 md:grid-cols-1 lg:grid-cols-2">
Expand Down
Loading