diff --git a/apps/frontend/src/app/(site)/analytics/page.tsx b/apps/frontend/src/app/(site)/analytics/page.tsx index f641396d..f4d67fb3 100644 --- a/apps/frontend/src/app/(site)/analytics/page.tsx +++ b/apps/frontend/src/app/(site)/analytics/page.tsx @@ -1,5 +1,4 @@ import {AnalyticsComponent} from "@gitroom/frontend/components/analytics/analytics.component"; -import {internalFetch} from "@gitroom/helpers/utils/internal.fetch"; import {Metadata} from "next"; export const metadata: Metadata = { @@ -8,14 +7,7 @@ export const metadata: Metadata = { } export default async function Index() { - const analytics = await (await internalFetch('/analytics')).json(); - const trending = await (await internalFetch('/analytics/trending')).json(); - const stars = await (await internalFetch('/analytics/stars', { - body: JSON.stringify({page: 1}), - method: 'POST' - })).json(); - return ( - + ); } diff --git a/apps/frontend/src/app/(site)/billing/page.tsx b/apps/frontend/src/app/(site)/billing/page.tsx index 5cdcacdc..393c03ea 100644 --- a/apps/frontend/src/app/(site)/billing/page.tsx +++ b/apps/frontend/src/app/(site)/billing/page.tsx @@ -1,7 +1,5 @@ -import { internalFetch } from '@gitroom/helpers/utils/internal.fetch'; import { BillingComponent } from '@gitroom/frontend/components/billing/billing.component'; import { Metadata } from 'next'; -import { redirect } from 'next/navigation'; export const metadata: Metadata = { title: 'Gitroom Billing', @@ -9,13 +7,5 @@ export const metadata: Metadata = { }; export default async function Page() { - const tiers = await (await internalFetch('/user/subscription/tiers')).json(); - if (tiers?.statusCode === 402) { - return redirect('/'); - } - const { subscription } = await ( - await internalFetch('/user/subscription') - ).json(); - - return ; + return ; } diff --git a/apps/frontend/src/app/(site)/launches/page.tsx b/apps/frontend/src/app/(site)/launches/page.tsx index cb351c5f..99014410 100644 --- a/apps/frontend/src/app/(site)/launches/page.tsx +++ b/apps/frontend/src/app/(site)/launches/page.tsx @@ -1,5 +1,4 @@ import {LaunchesComponent} from "@gitroom/frontend/components/launches/launches.component"; -import {internalFetch} from "@gitroom/helpers/utils/internal.fetch"; import {Metadata} from "next"; export const metadata: Metadata = { @@ -8,8 +7,7 @@ export const metadata: Metadata = { } export default async function Index() { - const {integrations} = await (await internalFetch('/integrations/list')).json(); return ( - + ); } diff --git a/apps/frontend/src/app/(site)/loading.tsx b/apps/frontend/src/app/(site)/loading.tsx new file mode 100644 index 00000000..5475c27b --- /dev/null +++ b/apps/frontend/src/app/(site)/loading.tsx @@ -0,0 +1,5 @@ +import { LoadingComponent } from '@gitroom/frontend/components/layout/loading'; + +export default function Loading() { + return ; +} diff --git a/apps/frontend/src/app/(site)/settings/page.tsx b/apps/frontend/src/app/(site)/settings/page.tsx index aacb59f2..f5ee1b8a 100644 --- a/apps/frontend/src/app/(site)/settings/page.tsx +++ b/apps/frontend/src/app/(site)/settings/page.tsx @@ -22,16 +22,5 @@ export default async function Index({ return redirect('/settings', RedirectType.replace); } - const { github } = await (await internalFetch('/settings/github')).json(); - if (!github) { - return redirect('/'); - } - const emptyOnes = github.find((p: { login: string }) => !p.login); - const { organizations } = emptyOnes - ? await ( - await internalFetch(`/settings/organizations/${emptyOnes.id}`) - ).json() - : { organizations: [] }; - - return ; + return ; } diff --git a/apps/frontend/src/components/analytics/analytics.component.tsx b/apps/frontend/src/components/analytics/analytics.component.tsx index e926dc7f..00b43a09 100644 --- a/apps/frontend/src/components/analytics/analytics.component.tsx +++ b/apps/frontend/src/components/analytics/analytics.component.tsx @@ -1,105 +1,141 @@ -import {StarsAndForks} from "@gitroom/frontend/components/analytics/stars.and.forks"; -import {FC} from "react"; -import {StarsAndForksInterface} from "@gitroom/frontend/components/analytics/stars.and.forks.interface"; -import {StarsTableComponent} from "@gitroom/frontend/components/analytics/stars.table.component"; +'use client'; -export const AnalyticsComponent: FC = (props) => { - return ( -
-
- -
-

Stars per day

-
- -
-
-
- {/*
*/} - {/*

News Feed

*/} - {/*
*/} - {/*
*/} - {/* Global*/} - {/*
*/} - {/*
*/} - {/* My Feed*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/* */} - {/*
*/} - {/*
*/} - {/*
Nevo David
*/} - {/*
05/06/2024
*/} - {/*
*/} - {/*
O atual sistema político precisa mudar para valorizar o trabalho e garantir igualdade de oportunidad
*/} - {/*
*/} - {/*
See Tweet
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/* */} - {/*
*/} - {/*
*/} - {/*
Nevo David
*/} - {/*
05/06/2024
*/} - {/*
*/} - {/*
O atual sistema político precisa mudar para valorizar o trabalho e garantir igualdade de oportunidad
*/} - {/*
*/} - {/*
See Tweet
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/* */} - {/*
*/} - {/*
*/} - {/*
Nevo David
*/} - {/*
05/06/2024
*/} - {/*
*/} - {/*
O atual sistema político precisa mudar para valorizar o trabalho e garantir igualdade de oportunidad
*/} - {/*
*/} - {/*
See Tweet
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/* */} - {/*
*/} - {/*
*/} - {/*
Nevo David
*/} - {/*
05/06/2024
*/} - {/*
*/} - {/*
O atual sistema político precisa mudar para valorizar o trabalho e garantir igualdade de oportunidad
*/} - {/*
*/} - {/*
See Tweet
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/* */} - {/*
*/} - {/*
*/} - {/*
Nevo David
*/} - {/*
05/06/2024
*/} - {/*
*/} - {/*
O atual sistema político precisa mudar para valorizar o trabalho e garantir igualdade de oportunidad
*/} - {/*
*/} - {/*
See Tweet
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} +import { StarsAndForks } from '@gitroom/frontend/components/analytics/stars.and.forks'; +import { FC, useCallback } from 'react'; +import { StarsTableComponent } from '@gitroom/frontend/components/analytics/stars.table.component'; +import useSWR from 'swr'; +import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; +import { LoadingComponent } from '@gitroom/frontend/components/layout/loading'; + +export const AnalyticsComponent: FC = () => { + const fetch = useFetch(); + + const load = useCallback(async (path: string) => { + return await (await fetch(path)).json(); + }, []); + + const starsCallback = useCallback(async (path: string) => { + return await ( + await fetch(path, { + body: JSON.stringify({ page: 1 }), + method: 'POST', + }) + ).json(); + }, []); + + const { isLoading: isLoadingAnalytics, data: analytics } = useSWR( + '/analytics', + load + ); + const { isLoading: isLoadingTrending, data: trending } = useSWR( + '/analytics/trending', + load + ); + const { isLoading: isLoadingStars, data: stars } = useSWR( + '/analytics/stars', + starsCallback + ); + + if (isLoadingAnalytics || isLoadingTrending || isLoadingStars) { + return ; + } + + return ( +
+
+ +
+

Stars per day

+
+ +
- ); -} \ No newline at end of file +
+ {/*
*/} + {/*

News Feed

*/} + {/*
*/} + {/*
*/} + {/* Global*/} + {/*
*/} + {/*
*/} + {/* My Feed*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/* */} + {/*
*/} + {/*
*/} + {/*
Nevo David
*/} + {/*
05/06/2024
*/} + {/*
*/} + {/*
O atual sistema político precisa mudar para valorizar o trabalho e garantir igualdade de oportunidad
*/} + {/*
*/} + {/*
See Tweet
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/* */} + {/*
*/} + {/*
*/} + {/*
Nevo David
*/} + {/*
05/06/2024
*/} + {/*
*/} + {/*
O atual sistema político precisa mudar para valorizar o trabalho e garantir igualdade de oportunidad
*/} + {/*
*/} + {/*
See Tweet
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/* */} + {/*
*/} + {/*
*/} + {/*
Nevo David
*/} + {/*
05/06/2024
*/} + {/*
*/} + {/*
O atual sistema político precisa mudar para valorizar o trabalho e garantir igualdade de oportunidad
*/} + {/*
*/} + {/*
See Tweet
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/* */} + {/*
*/} + {/*
*/} + {/*
Nevo David
*/} + {/*
05/06/2024
*/} + {/*
*/} + {/*
O atual sistema político precisa mudar para valorizar o trabalho e garantir igualdade de oportunidad
*/} + {/*
*/} + {/*
See Tweet
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/* */} + {/*
*/} + {/*
*/} + {/*
Nevo David
*/} + {/*
05/06/2024
*/} + {/*
*/} + {/*
O atual sistema político precisa mudar para valorizar o trabalho e garantir igualdade de oportunidad
*/} + {/*
*/} + {/*
See Tweet
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/} +
+ ); +}; diff --git a/apps/frontend/src/components/analytics/stars.and.forks.tsx b/apps/frontend/src/components/analytics/stars.and.forks.tsx index b24d3d71..4c2c01d8 100644 --- a/apps/frontend/src/components/analytics/stars.and.forks.tsx +++ b/apps/frontend/src/components/analytics/stars.and.forks.tsx @@ -1,65 +1,123 @@ -import {FC} from "react"; -import {StarsAndForksInterface} from "@gitroom/frontend/components/analytics/stars.and.forks.interface"; -import {Chart} from "@gitroom/frontend/components/analytics/chart"; -import Image from "next/image"; -import {UtcToLocalDateRender} from "../../../../../libraries/react-shared-libraries/src/helpers/utc.date.render"; -import clsx from "clsx"; +import { FC } from 'react'; +import { StarsAndForksInterface } from '@gitroom/frontend/components/analytics/stars.and.forks.interface'; +import { Chart } from '@gitroom/frontend/components/analytics/chart'; +import Image from 'next/image'; +import { UtcToLocalDateRender } from '../../../../../libraries/react-shared-libraries/src/helpers/utc.date.render'; +import clsx from 'clsx'; export const StarsAndForks: FC = (props) => { - const {list} = props; - return ( - <> - {list.map(item => ( -
- {[1,2].map(p => ( -
-
-
- Stars -
-
- {item.login.split('/')[1].split('').map(((char, index) => index === 0 ? char.toUpperCase() : char)).join('')} {p === 1 ? 'Stars' : 'Forks'} -
-
-
-
- {item.stars.length ? :
Processing stars...
} -
-
-
- {item?.stars[item.stars.length - 1]?.totalStars} -
-
- ))} + const { list } = props; + return ( + <> + {list.map((item) => ( +
+ {[1, 2].map((p) => ( +
+
+
+ Stars
- ))} -
- {[0, 1].map( p => ( -
-
-
- Trending -
-
- {p === 0 ? 'Last Github Trending' : 'Next Predicted GitHub Trending'} -
-
-
-
-
- -
-
- -
-
-
-
-
- -
-
-
))} +
+ {item.login + .split('/')[1] + .split('') + .map((char, index) => + index === 0 ? char.toUpperCase() : char + ) + .join('')}{' '} + {p === 1 ? 'Stars' : 'Forks'} +
+
+
+
+ {item.stars.length ? ( + + ) : ( +
+ Processing stars... +
+ )} +
+
+
+ {item?.stars[item.stars.length - 1]?.totalStars} +
- ); -} \ No newline at end of file + ))} +
+ ))} +
+ {[0, 1].map((p) => ( +
+
+
+ Trending +
+
+ {p === 0 + ? 'Last Github Trending' + : 'Next Predicted GitHub Trending'} +
+
+
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+ ))} +
+ + ); +}; diff --git a/apps/frontend/src/components/billing/billing.component.tsx b/apps/frontend/src/components/billing/billing.component.tsx index 13fefe91..9d428752 100644 --- a/apps/frontend/src/components/billing/billing.component.tsx +++ b/apps/frontend/src/components/billing/billing.component.tsx @@ -1,14 +1,29 @@ -import { FC } from 'react'; -import { Subscription } from '@prisma/client'; -import { - NoBillingComponent, - Tiers, -} from '@gitroom/frontend/components/billing/no.billing.component'; +"use client"; -export const BillingComponent: FC<{ - subscription?: Subscription; - tiers: Tiers; -}> = (props) => { - const { subscription, tiers } = props; - return ; +import { useCallback } from 'react'; +import { NoBillingComponent } from '@gitroom/frontend/components/billing/no.billing.component'; +import useSWR from 'swr'; +import { LoadingComponent } from '@gitroom/frontend/components/layout/loading'; +import {useFetch} from "@gitroom/helpers/utils/custom.fetch"; + +export const BillingComponent = () => { + const fetch = useFetch(); + const load = useCallback(async (path: string) => { + return await (await fetch(path)).json(); + }, []); + + const { isLoading: isLoadingTier, data: tiers } = useSWR( + '/user/subscription/tiers', + load + ); + const { isLoading: isLoadingSubscription, data: subscription } = useSWR( + '/user/subscription', + load + ); + + if (isLoadingSubscription || isLoadingTier) { + return ; + } + + return ; }; diff --git a/apps/frontend/src/components/launches/launches.component.tsx b/apps/frontend/src/components/launches/launches.component.tsx index 392b2b6a..7313baf7 100644 --- a/apps/frontend/src/components/launches/launches.component.tsx +++ b/apps/frontend/src/components/launches/launches.component.tsx @@ -1,18 +1,30 @@ +'use client'; + import { AddProviderButton } from '@gitroom/frontend/components/launches/add.provider.component'; -import { FC, useMemo } from 'react'; +import { FC, useCallback, useMemo } from 'react'; import Image from 'next/image'; import { orderBy } from 'lodash'; import { Calendar } from '@gitroom/frontend/components/launches/calendar'; import { CalendarWeekProvider, - Integrations, } from '@gitroom/frontend/components/launches/calendar.context'; import { Filters } from '@gitroom/frontend/components/launches/filters'; +import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; +import useSWR from 'swr'; -export const LaunchesComponent: FC<{ - integrations: Integrations[]; -}> = (props) => { - const { integrations } = props; +export const LaunchesComponent = () => { + const fetch = useFetch(); + const load = useCallback(async (path: string) => { + return (await (await fetch(path)).json()).integrations; + }, []); + + const { data: integrations } = useSWR( + '/integrations/list', + load, + { + fallbackData: [], + } + ); const sortedIntegrations = useMemo(() => { return orderBy(integrations, ['type', 'identifier'], ['desc', 'asc']); @@ -22,9 +34,7 @@ export const LaunchesComponent: FC<{
-
+

Channels

diff --git a/apps/frontend/src/components/layout/layout.settings.tsx b/apps/frontend/src/components/layout/layout.settings.tsx index 6ddb009b..d7523a19 100644 --- a/apps/frontend/src/components/layout/layout.settings.tsx +++ b/apps/frontend/src/components/layout/layout.settings.tsx @@ -1,4 +1,6 @@ -import { ReactNode } from 'react'; +'use client'; + +import { ReactNode, useCallback } from 'react'; import { Title } from '@gitroom/frontend/components/layout/title'; import { headers } from 'next/headers'; import { ContextWrapper } from '@gitroom/frontend/components/layout/user.context'; @@ -10,11 +12,22 @@ import Image from 'next/image'; import { Toaster } from '@gitroom/react/toaster/toaster'; import { ShowPostSelector } from '@gitroom/frontend/components/post-url-selector/post.url.selector'; import { OrganizationSelector } from '@gitroom/frontend/components/layout/organization.selector'; -import NotificationComponent from "@gitroom/frontend/components/notifications/notification.component"; -import Link from "next/link"; +import NotificationComponent from '@gitroom/frontend/components/notifications/notification.component'; +import Link from 'next/link'; +import useSWR from 'swr'; +import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; export const LayoutSettings = ({ children }: { children: ReactNode }) => { - const user = JSON.parse(headers().get('user')!); + const fetch = useFetch(); + const load = useCallback(async (path: string) => { + return await (await fetch(path)).json(); + }, []); + + const { data: user } = useSWR( + '/user/self', + load + ); + return ( diff --git a/apps/frontend/src/components/layout/loading.tsx b/apps/frontend/src/components/layout/loading.tsx new file mode 100644 index 00000000..600ff7b9 --- /dev/null +++ b/apps/frontend/src/components/layout/loading.tsx @@ -0,0 +1,6 @@ +'use client'; +import ReactLoading from 'react-loading'; + +export const LoadingComponent = () => { + return
; +}; diff --git a/apps/frontend/src/components/layout/top.menu.tsx b/apps/frontend/src/components/layout/top.menu.tsx index 21480dc0..a880dc5c 100644 --- a/apps/frontend/src/components/layout/top.menu.tsx +++ b/apps/frontend/src/components/layout/top.menu.tsx @@ -48,7 +48,7 @@ export const TopMenu: FC = () => { .map((item, index) => (
  • = ({ user, children }) => { + const values = user ? { ...user, tier: pricing[user.tier] } : ({} as any); return ( - + {children} ); diff --git a/apps/frontend/src/components/settings/settings.component.tsx b/apps/frontend/src/components/settings/settings.component.tsx index 6e42f9c7..7e5912a4 100644 --- a/apps/frontend/src/components/settings/settings.component.tsx +++ b/apps/frontend/src/components/settings/settings.component.tsx @@ -1,17 +1,52 @@ 'use client'; -import { Checkbox } from '@gitroom/react/form/checkbox'; import { GithubComponent } from '@gitroom/frontend/components/settings/github.component'; -import { FC } from 'react'; +import { useCallback, useEffect } from 'react'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; import { TeamsComponent } from '@gitroom/frontend/components/settings/teams.component'; +import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; +import useSWR from 'swr'; +import { LoadingComponent } from '@gitroom/frontend/components/layout/loading'; +import { useRouter } from 'next/navigation'; -export const SettingsComponent: FC<{ - organizations: Array<{ login: string; id: string }>; - github: Array<{ id: string; login: string }>; -}> = (props) => { - const { github, organizations } = props; +export const SettingsComponent = () => { const user = useUser(); + const router = useRouter(); + + const fetch = useFetch(); + + const load = useCallback(async (path: string) => { + const { github } = await (await fetch('/settings/github')).json(); + if (!github) { + return false; + } + + const emptyOnes = github.find((p: { login: string }) => !p.login); + const { organizations } = emptyOnes + ? await (await fetch(`/settings/organizations/${emptyOnes.id}`)).json() + : { organizations: [] }; + + return { github, organizations }; + }, []); + + const { isLoading: isLoadingSettings, data: loadAll } = useSWR( + 'load-all', + load + ); + + useEffect(() => { + if (!isLoadingSettings && !loadAll) { + router.push('/'); + } + }, [loadAll, isLoadingSettings]); + + if (isLoadingSettings) { + return ; + } + + if (!loadAll) { + return null; + } return (
    @@ -20,7 +55,10 @@ export const SettingsComponent: FC<{
    Connect your GitHub repository to receive updates and analytics
    - + {/*
    */} {/*
    */} {/* */} @@ -28,7 +66,7 @@ export const SettingsComponent: FC<{ {/*
    Show news with everybody in Gitroom
    */} {/*
    */}
    - {!!user?.tier.team_members && } + {!!user?.tier?.team_members && }
    ); }; diff --git a/apps/frontend/src/middleware.ts b/apps/frontend/src/middleware.ts index 79f948ed..c77b6951 100644 --- a/apps/frontend/src/middleware.ts +++ b/apps/frontend/src/middleware.ts @@ -84,27 +84,8 @@ export async function middleware(request: NextRequest) { return redirect; } - const userResponse = await fetchBackend('/user/self', { - headers: { - auth: authCookie?.value!, - ...(showorg?.value ? { showorg: showorg?.value! } : {}), - }, - }); + return NextResponse.next(); - if (userResponse.status === 401) { - return NextResponse.redirect(new URL('/auth/logout', nextUrl.href)); - } - - if ([200, 201].indexOf(userResponse.status) === -1) { - return NextResponse.redirect(new URL('/err', nextUrl.href)); - } - - const user = await userResponse.json(); - - const next = NextResponse.next(); - next.headers.set('user', JSON.stringify(user)); - - return next; } catch (err) { return NextResponse.redirect(new URL('/auth/logout', nextUrl.href)); }