Skip to content

Commit

Permalink
Merge branch 'apple-music' of https://github.com/statsfm/web into app…
Browse files Browse the repository at this point in the history
…le-music
  • Loading branch information
netlob committed Mar 7, 2024
2 parents e13cc7a + 50c4f2f commit 4a1bac5
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 71 deletions.
10 changes: 10 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ module.exports = withBundleAnalyzer({
destination: '/settings/imports',
permanent: true,
},
{
source: '/gift',
destination: '/settings/gift',
permanent: true,
},
{
source: '/gift/success',
destination: '/settings/gift/success',
permanent: true,
},
{
source: '/discord',
destination: 'https://stats.fm/discord',
Expand Down
6 changes: 5 additions & 1 deletion src/components/settings/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,13 @@ const NavBody: FC = () => (
<SideNavItem href="/settings/connections">Connections</SideNavItem>
</NavGroup>

<NavGroup title="Stats">
<NavGroup title="Stats & algorithms">
<SideNavItem href="/settings/imports">Imports</SideNavItem>
</NavGroup>

<NavGroup title="Plus">
<SideNavItem href="/settings/gift">Gifts</SideNavItem>
</NavGroup>
</aside>
</nav>
);
Expand Down
6 changes: 4 additions & 2 deletions src/pages/plus/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,9 @@ const PlusPage: NextPage<
</p>

<button
onClick={user?.isPlus ? () => router.push('/gift') : startCheckout}
onClick={
user?.isPlus ? () => router.push('/settings/gift') : startCheckout
}
className="m-0 p-0"
>
<a className="mt-12 block w-fit rounded-2xl bg-plus px-5 py-3 font-bold text-black hover:bg-plus/90 active:bg-plus/75">
Expand Down Expand Up @@ -659,7 +661,7 @@ const PlusPage: NextPage<
</button>
{user?.isPlus && (
<button
onClick={() => router.push('/gift')}
onClick={() => router.push('/settings/gift')}
className="m-0 w-full p-0"
>
<p className="block w-full rounded-lg bg-plus p-1 text-center font-medium text-black hover:bg-plus/90 active:bg-plus/75">
Expand Down
53 changes: 31 additions & 22 deletions src/pages/settings/connections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,38 @@ import type { SSRProps } from '@/utils/ssrUtils';
import { fetchUser } from '@/utils/ssrUtils';
import { event } from 'nextjs-google-analytics';

const PlatformStatus = {
LOADING: 'LOADING',
CONNECTED: 'CONNECTED',
DISCONNECTED: 'DISCONNECTED',
} as const;
enum PlatformStatus {
LOADING = 'LOADING',
CONNECTED = 'CONNECTED',
DISCONNECTED = 'DISCONNECTED',
}

type PlatformType = {
type SocialPlatform = {
status: keyof typeof PlatformStatus;
key: string;
name: string;
icon: string;
can_refresh?: boolean;
canRefresh?: boolean;
description: string;
connection: UserSocialMediaConnection | null;
connect: () => void;
update?: () => void;
disconnect: () => void;
};

const useConnections = () => {
const useSocials = () => {
const api = useApi();

const initialPlatforms: PlatformType[] = [
const initialPlatforms: SocialPlatform[] = [
{
status: PlatformStatus.LOADING,
key: 'discord',
name: 'Discord',
icon: 'https://cdn.stats.fm/file/statsfm/images/brands/discord/color.svg',
description:
'Connect your Discord account to get access to personalized commands with the stats.fm Discord bot',
connection: null as UserSocialMediaConnection | null,
can_refresh: true,
'Connect your Discord account to get access to personalized commands with the stats.fm Discord bot, and show your Discord profile on your stats.fm profile.',
connection: null,
canRefresh: true,
// TODO: optimistic updates for connecting
connect: () => {
event('SETTINGS_connections_discord_connect');
Expand Down Expand Up @@ -74,7 +74,7 @@ const useConnections = () => {

const refetch = async () => {
const userConnections = await api.me.socialMediaConnections();
const hydratedPlatforms = platforms.map<PlatformType>((platform) => {
const hydratedPlatforms = platforms.map<SocialPlatform>((platform) => {
const connection = userConnections.find(
(connection) => connection.platform.name === platform.name
);
Expand All @@ -92,10 +92,11 @@ const useConnections = () => {
disconnect: async () => {
await api.me.removeSocialMediaConnection(connection.id);

const optimisticPlatforms = platforms.map<PlatformType>((platform) =>
platform.name === connection.platform.name
? { ...platform, status: PlatformStatus.DISCONNECTED }
: platform
const optimisticPlatforms = platforms.map<SocialPlatform>(
(platform) =>
platform.name === connection.platform.name
? { ...platform, status: PlatformStatus.DISCONNECTED }
: platform
);
setPlatforms(optimisticPlatforms);
platform.disconnect();
Expand All @@ -113,16 +114,24 @@ const useConnections = () => {
return platforms;
};

// const useStreamingServices = () => {
// return [];
// };

// TODO: prefetch connections on the server
const ConnectionsList = () => {
const platforms = useConnections();
// const streamingServices = useStreamingServices();
const socials = useSocials();

return (
<div className="relative w-full">
<SettingsHeader title="Connections" />
<h2>Streaming services</h2>
<p>Coming soon...</p>

<h2>Socials</h2>
<ul className="grid grid-cols-1 gap-4 lg:grid-cols-2">
{platforms.map((platform) => (
{socials.map((platform) => (
<li
className="mb-4 w-full rounded-xl bg-foreground py-4 px-5"
key={platform.key}
Expand All @@ -144,14 +153,14 @@ const ConnectionsList = () => {
</div>
<div className="flex flex-col gap-2 lg:flex-row">
{platform.status === PlatformStatus.CONNECTED &&
platform.can_refresh &&
platform.canRefresh &&
'update' in platform && (
<Button
className="mt-auto h-min rounded-xl px-4 py-2"
disabled={!platform.can_refresh}
disabled={!platform.canRefresh}
onClick={
platform.status === PlatformStatus.CONNECTED &&
platform.can_refresh &&
platform.canRefresh &&
'update' in platform
? platform.update
: () => {}
Expand Down
111 changes: 70 additions & 41 deletions src/pages/gift/index.tsx → src/pages/settings/gift/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import type { GetServerSideProps, NextPage } from 'next';
import { Container } from '@/components/Container';
import type { FC } from 'react';
import { useCallback, useMemo, useEffect, useState } from 'react';
import { useApi, useAuth, useToaster } from '@/hooks';
import { Button } from '@/components/Button';
import type { Plan } from '@/types/gift';
import { Coupon } from '@/components/Gift/Coupon';
import { Title } from '@/components/Title';
Expand All @@ -13,6 +11,10 @@ import { useRemoteValue } from '@/hooks/use-remote-config';
import { MdInfo } from 'react-icons/md';
import type { SSRProps } from '@/utils/ssrUtils';
import { fetchUser } from '@/utils/ssrUtils';
import { AccountLayout } from '@/components/settings/Layout';
import { SettingsHeader } from '@/components/settings/SettingsHeader';
import clsx from 'clsx';
import { Button } from '@/components/Button';

const Coupons: FC = () => {
const [giftCodes, setGiftCodes] = useState<GiftCode[]>([]);
Expand Down Expand Up @@ -116,7 +118,7 @@ export const getServerSideProps: GetServerSideProps<SSRProps<Props>> = async (
};
};

const GiftPage: NextPage<Props> = ({ plans }) => {
const Gift: FC<Props> = ({ plans }) => {
const toaster = useToaster();

const giftNoticeText = useRemoteValue('gift_notice_text');
Expand Down Expand Up @@ -163,7 +165,8 @@ const GiftPage: NextPage<Props> = ({ plans }) => {
);

return (
<Container className="pt-32">
<div className="relative w-full">
<SettingsHeader title="Gifts" />
<Title>Gift</Title>
{giftNoticeShow?.asBoolean() && (
<div className="my-8 w-full flex-row rounded-md border-l-4 border-l-yellow-400/80 bg-yellow-400/20 p-4">
Expand All @@ -179,67 +182,82 @@ const GiftPage: NextPage<Props> = ({ plans }) => {
</div>
)}
<section className="mb-5 mt-2 flex flex-col gap-3">
<div v-if="plans" className="flex w-full flex-col justify-between">
<div className="flex w-full flex-col justify-between">
{plans.length > 0 ? (
<div className="mb-2 flex flex-col justify-center gap-3 md:flex-row">
<div className="isolate mx-auto mb-2 mt-10 grid max-w-md grid-cols-1 gap-8 lg:mx-0 lg:max-w-none xl:grid-cols-2">
{plans.map((plan) => (
<article
<div
key={plan.id}
className="relative w-full cursor-pointer select-none transition duration-200 hover:scale-105"
onClick={() => startCheckout(plan.id)}
className="rounded-3xl bg-foreground p-8 xl:p-10"
>
<div className="flex max-h-max w-full flex-col items-center rounded-2xl bg-foreground p-5 py-3 text-center">
{plan.isMostChosen && (
<div className="absolute top-0 -translate-y-1/2 select-none rounded-lg bg-primary px-3">
<span className="font-medium text-foreground">
Most chosen
</span>
</div>
<div className="flex items-center justify-between gap-x-4">
<h3
id={plan.id}
className="text-xl font-semibold leading-8 text-white"
>
{plan.name}
</h3>
{plan.isMostChosen ? (
<p className="rounded-full bg-primary px-2.5 py-1 text-xs font-semibold leading-5 text-white">
Most chosen
</p>
) : (
<p className="rounded-full px-2.5 py-1 text-xs font-semibold leading-5 text-transparent">
-
</p>
)}
<h1>{plan.quantity}x</h1>
<p>{plan.name}</p>
<p className="my-[-3px] font-bold text-primary">
{calculateSavePercentage(plan, plans[0]!) > 0 ? (
<>
Save {calculateSavePercentage(plan, plans[0]!)}% with
this bundle!
</>
) : (
<span className="text-transparent">-</span>
)}
</div>

<p className="mt-2 flex items-baseline gap-x-1">
<span className="text-lg font-bold tracking-tight text-white">
{formatAmount(plan.price.amount)}
{plan.price.currency}
<small className="ml-1">excl vat & fees</small>
</span>
</p>
{calculateSavePercentage(plan, plans[0]!) > 0 ? (
<p className="my-4 font-bold text-primary">
Save {calculateSavePercentage(plan, plans[0]!)}% with this
bundle!
</p>
) : (
<p className="my-4 font-bold text-transparent">-</p>
)}
<div className="mt-auto flex flex-row gap-5 pt-4">
<Button
onClick={() => startCheckout(plan.id)}
className={clsx(
plan.isMostChosen
? ''
: 'bg-white/10 text-white focus-visible:outline-white hover:bg-white/20',
'mt-6 block w-full rounded-md py-2 px-3 text-center text-sm font-semibold leading-6 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2'
)}
>
Buy plan
</Button>
</div>
<Button className="mt-2 w-full rounded-xl py-2 text-sm">
{formatAmount(plan.price.amount)}
{plan.price.currency}
<small className="ml-1">excl vat & fees</small>
</Button>
</article>
</div>
))}
</div>
) : (
<div className="flex flex-col items-center justify-center">
Loading...
</div>
)}
<span>
* you can redeem a coupon yourself or send the coupon to a friend
</span>
</div>
</section>
<section>
<h2>How does it work?</h2>
<article className="prose max-w-full font-medium text-neutral-400 prose-headings:text-white prose-a:text-primary prose-li:my-0.5">
<ol>
<li>Log in if you arent&apos;t already</li>
<li>Choose between one of the packages</li>
<li>
You&apos;ll be redirected to a secure{' '}
<a href="https://stripe.com">Stripe</a> checkout page
</li>
<li>
After finishing the checkout process your coupons will be shown in
the list below
After finishing the checkout process, your coupons will be shown
in <Link href="#your-coupons">the list below</Link>.
</li>
<li>
If you want to claim the Plus yourself, you can enter it yourself
Expand All @@ -258,8 +276,19 @@ const GiftPage: NextPage<Props> = ({ plans }) => {
</ol>
</article>
</section>
{user && <Coupons />}
</Container>
<Coupons />
</div>
);
};

const GiftPage: NextPage<Props> = (props) => {
const { user } = useAuth();
if (!user) return null;

return (
<AccountLayout>
<Gift {...props} />
</AccountLayout>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ const SuccessPage: NextPage<Props> = ({ gif }) => {
</h1>
<p className="mt-2 max-w-prose font-bold text-text-grey">
Your gift codes will show up on the{' '}
<Link legacyBehavior href="/gift#your-coupons">
<Link legacyBehavior href="/settings/gift#your-coupons">
<a className="font-bold text-primary hover:underline hover:opacity-90">
gift page
</a>
</Link>
. If they aren&apos;t on the{' '}
<Link legacyBehavior href="/gift#your-coupons">
<Link legacyBehavior href="/settings/gift#your-coupons">
<a className="font-bold text-primary hover:underline hover:opacity-90">
gift page
</a>
Expand All @@ -70,7 +70,10 @@ const SuccessPage: NextPage<Props> = ({ gif }) => {
after 24 hours, send an email with your order id (sent by Stripe in
your email) to [email protected]
</p>
<Button className="mt-5 max-w-fit" onClick={() => router.push('/gift')}>
<Button
className="mt-5 max-w-fit"
onClick={() => router.push('/settings/gift')}
>
Take me to the coupons page
</Button>
</div>
Expand Down
9 changes: 7 additions & 2 deletions src/pages/settings/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -362,10 +362,15 @@ const DeleteAccount: FC = () => {
);
};

const AccountPrivacyInfoForm: FC<{
type AccountPrivacyInfoFormProps = {
pronouns: Pronoun[];
user: UserPrivate;
}> = ({ pronouns, user }) => {
};

const AccountPrivacyInfoForm: FC<AccountPrivacyInfoFormProps> = ({
pronouns,
user,
}) => {
const {
displayName: [displayName, setDisplayName],
customId: [customId, setCustomId],
Expand Down

0 comments on commit 4a1bac5

Please sign in to comment.