Skip to content
Merged
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
7 changes: 6 additions & 1 deletion .github/workflows/build-and-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ name: MoonCode CI/CD Pipeline - Build api and web app docker images and deploy t
on:
push:
branches: "main"
pull_request:
branches: "main"
workflow_dispatch:

jobs:
Expand Down Expand Up @@ -53,6 +55,9 @@ jobs:
uses: actions/checkout@v6

- name: Log in to Docker Hub
if: |
github.event_name == 'push' ||
(github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main')
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
Expand All @@ -69,7 +74,7 @@ jobs:
context: .
file: ${{ matrix.dockerfile }}
platforms: linux/amd64
push: true
push: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') }}
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image }}:${{ github.sha }}
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image }}:latest
Expand Down
3 changes: 3 additions & 0 deletions apps/api/src/app-router/providers/app-router.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export const appRouterProvider = {
...authRouter.procedures(),
...extensionRouter.procedures(),
...analyticsRouter.procedures(),
health: {
ping: trpcService.publicProcedure().query(() => ({ status: "OK" })),
},
});

return appRouter;
Expand Down
91 changes: 91 additions & 0 deletions apps/dashboard/src/app/app-error-boundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { useState } from "react";
import { ErrorBoundary } from "react-error-boundary";
import { Link } from "react-router";
import superjson from "superjson";

import { FallBackRender } from "@/components/errors/error-boundary";
import { SuspenseBoundary } from "@/components/errors/suspense-boundary";
import { AppSidebar } from "@/components/layout/app-sidebar/app-sidebar";
import { AppSidebarError } from "@/components/layout/app-sidebar/app-sidebar-error";
import { AppSidebarSkeleton } from "@/components/layout/app-sidebar/app-sidebar-skeleton";
import { Footer } from "@/components/layout/footer";
import { Header } from "@/components/layout/header/header";
import { NavigationResetWrapper } from "@/components/layout/navigation-reset-wrapper";
import { ThemeProvider } from "@/providers/theme-provider";
import { getQueryClient } from "@/utils/query-client";
import { TRPCProvider } from "@/utils/trpc";
import { type AppRouter } from "@repo/trpc/router";
import { ScrollToTopButton } from "@repo/ui/components/scroll-to-top-button";
import { Button } from "@repo/ui/components/ui/button";
import { SidebarProvider } from "@repo/ui/components/ui/sidebar";
import { TooltipProvider } from "@repo/ui/components/ui/tooltip";
import { QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { createTRPCClient, httpBatchLink } from "@trpc/client";

export const AppErrorBoundary = () => {
const queryClient = getQueryClient();
const [trpcClient] = useState(() =>
createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: import.meta.env.VITE_API_URL,
fetch(url, options) {
return fetch(url, {
...options,
credentials: "include",
});
},
transformer: superjson,
}),
],
}),
);

return (
<ThemeProvider>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} position="bottom" />
<TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
<SidebarProvider className="flex-1">
<TooltipProvider>
<NavigationResetWrapper>
<ErrorBoundary
FallbackComponent={({ error, resetErrorBoundary }) => (
<FallBackRender
error={error}
resetErrorBoundary={resetErrorBoundary}
hasCustomChildren={true}
customChildren={(errorMessage) => (
<AppSidebarError errorMessage={errorMessage} />
)}
/>
)}
>
<SuspenseBoundary
hasCustomSkeleton={true}
skeleton={<AppSidebarSkeleton />}
>
<AppSidebar />
</SuspenseBoundary>
</ErrorBoundary>

<div className="flex flex-1 flex-col">
<Header />
<main className="flex flex-1 flex-col items-center justify-center gap-y-12 pt-2 pr-14 pb-4 pl-1 max-md:pl-14">
<h2 className="text-5xl">An error occurred</h2>
<Button asChild className="w-44">
<Link to="/dashboard">Go Home</Link>
</Button>
</main>
<Footer />
</div>
<ScrollToTopButton />
</NavigationResetWrapper>
</TooltipProvider>
</SidebarProvider>
</TRPCProvider>
</QueryClientProvider>
</ThemeProvider>
);
};
57 changes: 9 additions & 48 deletions apps/dashboard/src/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,22 @@
import { useState } from "react";
import { ErrorBoundary } from "react-error-boundary";
import { Outlet } from "react-router";
import superjson from "superjson";

import { FallBackRender } from "@/components/errors/error-boundary";
import { NavigationResetWrapper } from "@/components/layout/navigation-reset-wrapper";
import { useExtensionWebsocket } from "@/hooks/use-extension-websocket";
import { useSetupOnlineManager } from "@/hooks/use-setup-online-manager";
import { ThemeProvider } from "@/providers/theme-provider";
import { isTRPCClientError, TRPCProvider } from "@/utils/trpc";
import { getQueryClient } from "@/utils/query-client";
import { TRPCProvider } from "@/utils/trpc";
import type { AppRouter } from "@repo/trpc/router";
import { ScrollToTopButton } from "@repo/ui/components/scroll-to-top-button";
import { SidebarProvider } from "@repo/ui/components/ui/sidebar";
import { Toaster } from "@repo/ui/components/ui/sonner";
import { TooltipProvider } from "@repo/ui/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { createTRPCClient, httpBatchLink } from "@trpc/client";

function makeQueryClient() {
return new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000,
refetchOnWindowFocus: true,
refetchInterval: 60 * 1000,
retry: (failureCount, error) => {
if (isTRPCClientError(error)) {
return failureCount < 1;
}

return failureCount < 3;
},
},
},
});
}

let browserQueryClient: QueryClient | undefined = undefined;

function getQueryClient() {
if (typeof window === "undefined") {
return makeQueryClient();
} else {
if (!browserQueryClient) browserQueryClient = makeQueryClient();
return browserQueryClient;
}
}

export const App = () => {
const queryClient = getQueryClient();
const [trpcClient] = useState(() =>
Expand All @@ -68,6 +38,7 @@ export const App = () => {
);

useExtensionWebsocket();
useSetupOnlineManager();

return (
<ThemeProvider>
Expand All @@ -76,20 +47,10 @@ export const App = () => {
<TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
<SidebarProvider>
<TooltipProvider>
<ErrorBoundary
FallbackComponent={({ error, resetErrorBoundary }) => (
<FallBackRender
error={error}
resetErrorBoundary={resetErrorBoundary}
hasCustomChildren={false}
/>
)}
>
<NavigationResetWrapper>
<Outlet />
<ScrollToTopButton />
</NavigationResetWrapper>
</ErrorBoundary>
<NavigationResetWrapper>
<Outlet />
<ScrollToTopButton />
</NavigationResetWrapper>
</TooltipProvider>
</SidebarProvider>
</TRPCProvider>
Expand Down
8 changes: 5 additions & 3 deletions apps/dashboard/src/app/pages/auth/forgot-password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ export const ForgotPassword = () => {
usePageTitle("Forgot Password | MoonCode");

return (
<main className="flex items-center gap-2">
<Night className="relative flex size-full h-dvh w-[50%] max-[42.5rem]:hidden" />
<main className="flex min-h-dvh gap-2">
<div className="relative w-1/2 max-[42.5rem]:hidden">
<Night className="absolute h-full" />
</div>

<div className="flex h-dvh w-[50%] items-center justify-center max-[42.5rem]:w-full">
<div className="flex w-1/2 items-center justify-center max-[42.5rem]:w-full">
<ForgotPasswordForm />
</div>
</main>
Expand Down
8 changes: 5 additions & 3 deletions apps/dashboard/src/app/pages/auth/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ export const Login = () => {
}, []);

return (
<main className="flex items-center gap-2">
<Night className="relative flex size-full h-dvh w-[50%] max-[42.5rem]:hidden" />
<main className="flex min-h-dvh gap-2">
<div className="relative w-1/2 max-[42.5rem]:hidden">
<Night className="absolute h-full" />
</div>

<div className="flex h-dvh w-[50%] items-center justify-center max-[42.5rem]:w-full">
<div className="flex w-1/2 items-center justify-center max-[42.5rem]:w-full">
<LoginForm />
</div>
</main>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ export const CodeVerification = () => {
usePageTitle("Verify Reset Code | MoonCode");

return (
<main className="flex items-center gap-2">
<Night className="relative flex size-full h-dvh w-[50%] max-[42.5rem]:hidden" />
<main className="flex min-h-dvh gap-2">
<div className="relative w-1/2 max-[42.5rem]:hidden">
<Night className="absolute h-full" />
</div>

<div className="flex h-dvh w-[50%] items-center justify-center max-[42.5rem]:w-full">
<div className="flex w-1/2 items-center justify-center max-[42.5rem]:w-full">
<CodeVerificationForm />
</div>
</main>
Expand Down
8 changes: 5 additions & 3 deletions apps/dashboard/src/app/pages/auth/register-finish.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ export const RegisterFinish = () => {
usePageTitle("Register | MoonCode");

return (
<main className="flex items-center gap-2">
<Night className="relative flex size-full h-dvh w-[50%] max-[42.5rem]:hidden" />
<main className="flex min-h-dvh gap-2">
<div className="relative w-1/2 max-[42.5rem]:hidden">
<Night className="absolute h-full" />
</div>

<div className="flex h-dvh w-[50%] items-center justify-center max-[42.5rem]:w-full">
<div className="flex w-1/2 items-center justify-center max-[42.5rem]:w-full">
<RegisterFinishForm />
</div>
</main>
Expand Down
8 changes: 5 additions & 3 deletions apps/dashboard/src/app/pages/auth/register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ export const Register = () => {
usePageTitle("Register | MoonCode");

return (
<main className="flex items-center gap-2">
<Night className="relative flex size-full h-dvh w-[50%] max-[42.5rem]:hidden" />
<main className="flex min-h-dvh gap-2">
<div className="relative w-1/2 max-[42.5rem]:hidden">
<Night className="absolute h-full" />
</div>

<div className="flex h-dvh w-[50%] items-center justify-center max-[42.5rem]:w-full">
<div className="flex w-1/2 items-center justify-center max-[42.5rem]:w-full">
<RegisterForm />
</div>
</main>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ export const CodeVerification = () => {
usePageTitle("Register | MoonCode");

return (
<main className="flex items-center gap-2">
<Night className="relative flex size-full h-dvh w-[50%] max-[42.5rem]:hidden" />
<main className="flex min-h-dvh gap-2">
<div className="relative w-1/2 max-[42.5rem]:hidden">
<Night className="absolute h-full" />
</div>

<div className="flex h-dvh w-[50%] items-center justify-center max-[42.5rem]:w-full">
<div className="flex w-1/2 items-center justify-center max-[42.5rem]:w-full">
<CodeVerificationForm />
</div>
</main>
Expand Down
8 changes: 5 additions & 3 deletions apps/dashboard/src/app/pages/auth/reset-password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ export const ResetPassword = () => {
usePageTitle("Reset your password | MoonCode");

return (
<main className="flex items-center gap-2">
<Night className="relative flex size-full h-dvh w-[50%] max-[42.5rem]:hidden" />
<main className="flex min-h-dvh gap-2">
<div className="relative w-1/2 max-[42.5rem]:hidden">
<Night className="absolute h-full" />
</div>

<div className="flex h-dvh w-[50%] items-center justify-center max-[42.5rem]:w-full">
<div className="flex w-1/2 items-center justify-center max-[42.5rem]:w-full">
<ResetPasswordForm />
</div>
</main>
Expand Down
8 changes: 5 additions & 3 deletions apps/dashboard/src/app/pages/update-email/update-email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ export const UpdateEmail = () => {
usePageTitle("Update email | MoonCode");

return (
<main className="flex items-center gap-2">
<Night className="relative flex size-full h-dvh w-[50%] max-[42.5rem]:hidden" />
<main className="flex min-h-dvh gap-2">
<div className="relative w-1/2 max-[42.5rem]:hidden">
<Night className="absolute h-full" />
</div>

<div className="flex h-dvh w-[50%] items-center justify-center max-[42.5rem]:w-full">
<div className="flex w-1/2 items-center justify-center max-[42.5rem]:w-full">
<UpdateEmailForm />
</div>
</main>
Expand Down
2 changes: 2 additions & 0 deletions apps/dashboard/src/app/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ import { redirectToNotFoundLoader } from "@/loaders/redirect-to-not-found-loader
import { rootLoader } from "@/loaders/root-loader";

import { App } from "./app";
import { AppErrorBoundary } from "./app-error-boundary";
import { RegisterFinish } from "./pages/auth/register-finish";
import { Profile } from "./pages/profile/profile";

const router = createBrowserRouter([
{
element: <App />,
ErrorBoundary: () => <AppErrorBoundary />,
children: [
{
element: <Layout />,
Expand Down
4 changes: 2 additions & 2 deletions apps/dashboard/src/components/common/day-chart-title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const DayChartTitle = ({
<h2 className="flex items-center justify-between gap-4 px-3 text-center text-2xl font-bold">
<Icon
Icon={ChevronLeft}
className="max-[20.5rem]:hidden"
className="shrink-0 max-[20.5rem]:hidden"
onClick={handleChevronLeftClick}
/>
<div className="inline-block max-[26.25rem]:text-lg max-[24.375rem]:text-sm max-[20.5rem]:w-full">
Expand All @@ -50,7 +50,7 @@ export const DayChartTitle = ({
</div>
<Icon
Icon={ChevronRight}
className="max-[20.5rem]:hidden"
className="shrink-0 max-[20.5rem]:hidden"
onClick={handleChevronRightClick}
// deactivate the next date button if we are "Today"
disabled={isSameDay(date, new Date())}
Expand Down
Loading