diff --git a/opensaas-sh/app_diff/.env.vault.diff b/opensaas-sh/app_diff/.env.vault.diff index 9386736..85024a8 100644 --- a/opensaas-sh/app_diff/.env.vault.diff +++ b/opensaas-sh/app_diff/.env.vault.diff @@ -7,8 +7,8 @@ +#/--------------------------------------------------/ + +# development -+DOTENV_VAULT_DEVELOPMENT="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" -+DOTENV_VAULT_DEVELOPMENT_VERSION=5 ++DOTENV_VAULT_DEVELOPMENT="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" ++DOTENV_VAULT_DEVELOPMENT_VERSION=6 + +# ci +DOTENV_VAULT_CI="uIKC5RKdFeJiCAzoQ9e2oaT2EbR8usJcZIYlSoFl3HTFrh7J/qfo+Z+OqBgJKQllvCVIK4oQUsLICVWCRs+7yWp5j6gn2yu67lN4lKAfX0QCF/VFYNWa6u1NWZGT1bPRlvNIY7z/YnJZfgaq8Uj+mSU+C14KHMMCpKCSkbqqFX8AWlcPSkbjXaJP4IL3HxzPUGTMfq/+XbokI9r1UjBNYi1yus6jGjI4U2OtiDc61LZJ6Y0tsBeA8NA0iT2S+lwTJBjTmGHoMMjtK08Iw8GAXv9eejETvbHZfFTOpphIjeFXjFRUsgRfuPP3p/lErfncXofQ++9KNS5lhxINGBXQIKh2CRnjhajut38Xxr848YNAj4Ie4RKzeU1+aC6BXONhbD7qZQJmm63vtwTKwrUf8ML7T27DwdpV7dTdz5/W3UWnmbzhfI1pLeCHpBC1FrLBaxhFNFlkqsXiopen4iJf4ihWICn1hMCBGGRosKQJdj+y65FJMwraBbEVHa29FHYruhAPGFqGfEIWvQ++LXlPguJM/RL2txMoVppDanOwFCM3dMO3sF55BEuSSNJWX2s72ZDgTW4/Il7YiIBwwxChPs5vOQweYKqOd21HCl4t+ocu95ja3ZGROnhff72j2pCk7cahaVl/PS8WU7nZ1JQtkv5vNRR3nHgAH1nS9tSBDJ8twKEQ4bJcu2qdhGeQwenKRsV4nrKooGnQ8UlsvoTyozYYCseds2/iXX5vlc/lhL1fgcPPxoss2p+lDaS3AIIEMq0/TUCeRF2ImYUIMnnvCEb0T32Pz8bIfPblSThETdQ5A7ZRjyU9T9Ff6lpxqQwGUWO/ElKZ/CDsoeuj1UqOVLGRBwThrOHlU7LZ6kJnBvcy6AmWccE5fLsmf1l189FwMH6CimHIg2OC4ndCbiRKiP3+3OYHL0JSkTt8Lrsu/b+Mu0Kmiks1A16Sx2Lu1lUfPSsbAgYRYni7OkpgCOJ5DdnP607LTFVIichq4+KzQsc=" diff --git a/opensaas-sh/app_diff/main.wasp.diff b/opensaas-sh/app_diff/main.wasp.diff index f76025c..a2ee6eb 100644 --- a/opensaas-sh/app_diff/main.wasp.diff +++ b/opensaas-sh/app_diff/main.wasp.diff @@ -84,7 +84,7 @@ }, }, } -@@ -323,7 +321,10 @@ +@@ -195,7 +193,10 @@ email String? @unique username String? @unique lastActiveTimestamp DateTime @default(now()) diff --git a/opensaas-sh/app_diff/src/client/admin/pages/DashboardPage.tsx.diff b/opensaas-sh/app_diff/src/admin/dashboards/analytics/AnalyticsDashboardPage.tsx.diff similarity index 82% rename from opensaas-sh/app_diff/src/client/admin/pages/DashboardPage.tsx.diff rename to opensaas-sh/app_diff/src/admin/dashboards/analytics/AnalyticsDashboardPage.tsx.diff index aa36091..4a99931 100644 --- a/opensaas-sh/app_diff/src/client/admin/pages/DashboardPage.tsx.diff +++ b/opensaas-sh/app_diff/src/admin/dashboards/analytics/AnalyticsDashboardPage.tsx.diff @@ -1,27 +1,23 @@ ---- template/app/src/client/admin/pages/DashboardPage.tsx -+++ opensaas-sh/app/src/client/admin/pages/DashboardPage.tsx -@@ -1,5 +1,7 @@ +--- template/app/src/admin/dashboards/analytics/AnalyticsDashboardPage.tsx ++++ opensaas-sh/app/src/admin/dashboards/analytics/AnalyticsDashboardPage.tsx +@@ -1,4 +1,5 @@ import { type User } from 'wasp/entities'; - import { useQuery, getDailyStats } from 'wasp/client/operations'; -+import { Link } from "wasp/client/router"; +import { useState, useEffect } from 'react'; - import TotalSignupsCard from '../components/TotalSignupsCard'; - import TotalPageViewsCard from '../components/TotalPaidViewsCard'; - import TotalPayingUsersCard from '../components/TotalPayingUsersCard'; -@@ -10,6 +12,8 @@ + import { useQuery, getDailyStats } from 'wasp/client/operations'; + import TotalSignupsCard from './TotalSignupsCard'; + import TotalPageViewsCard from './TotalPageViewsCard'; +@@ -10,6 +11,7 @@ import { useHistory } from 'react-router-dom'; const Dashboard = ({ user }: { user: User }) => { + const [isDemoInfoVisible, setIsDemoInfoVisible] = useState(false); -+ const history = useHistory(); if (!user.isAdmin) { history.push('/'); -@@ -17,8 +21,41 @@ +@@ -17,8 +19,40 @@ const { data: stats, isLoading, error } = useQuery(getDailyStats); -+ + useEffect(() => { + try { + if (localStorage.getItem('isStripeDemoInfoVisible') === 'false') { diff --git a/opensaas-sh/app_diff/src/client/admin/components/UsersTable.tsx.diff b/opensaas-sh/app_diff/src/admin/dashboards/users/UsersTable.tsx.diff similarity index 79% rename from opensaas-sh/app_diff/src/client/admin/components/UsersTable.tsx.diff rename to opensaas-sh/app_diff/src/admin/dashboards/users/UsersTable.tsx.diff index bd452d2..98a91cf 100644 --- a/opensaas-sh/app_diff/src/client/admin/components/UsersTable.tsx.diff +++ b/opensaas-sh/app_diff/src/admin/dashboards/users/UsersTable.tsx.diff @@ -1,19 +1,21 @@ ---- template/app/src/client/admin/components/UsersTable.tsx -+++ opensaas-sh/app/src/client/admin/components/UsersTable.tsx -@@ -11,6 +11,7 @@ +--- template/app/src/admin/dashboards/users/UsersTable.tsx ++++ opensaas-sh/app/src/admin/dashboards/users/UsersTable.tsx +@@ -9,8 +9,10 @@ + const [skip, setskip] = useState(0); + const [page, setPage] = useState(1); const [email, setEmail] = useState(undefined); ++ const [isAdminFilter, setIsAdminFilter] = useState(undefined); const [statusOptions, setStatusOptions] = useState([]); + const [isDemoInfoVisible, setIsDemoInfoVisible] = useState(false); const { data, isLoading, error } = useQuery(getPaginatedUsers, { skip, emailContains: email, -@@ -26,8 +27,43 @@ +@@ -26,8 +28,42 @@ setskip((page - 1) * 10); }, [page]); -+ -+ useEffect(() => { ++ useEffect(() => { + try { + if (localStorage.getItem('isDemoInfoVisible') === 'false') { + // do nothing @@ -25,14 +27,14 @@ + } + }, []); + -+ const handleDemoInfoClose = () => { -+ try { -+ localStorage.setItem('isDemoInfoVisible', 'false'); -+ setIsDemoInfoVisible(false); -+ } catch (error) { -+ console.error(error); -+ } -+ }; ++ const handleDemoInfoClose = () => { ++ try { ++ localStorage.setItem('isDemoInfoVisible', 'false'); ++ setIsDemoInfoVisible(false); ++ } catch (error) { ++ console.error(error); ++ } ++ }; + return (
diff --git a/opensaas-sh/app_diff/src/client/landing-page/LandingPage.tsx.diff b/opensaas-sh/app_diff/src/client/landing-page/LandingPage.tsx.diff index 0060c36..f7c8a05 100644 --- a/opensaas-sh/app_diff/src/client/landing-page/LandingPage.tsx.diff +++ b/opensaas-sh/app_diff/src/client/landing-page/LandingPage.tsx.diff @@ -24,7 +24,7 @@ import { UserMenuItems } from '../../user/UserMenuItems'; -import { DocsUrl } from '../../common'; +import { DocsUrl, GithubUrl } from '../../common'; - import DarkModeSwitcher from '../admin/components/DarkModeSwitcher'; + import DarkModeSwitcher from '../components/DarkModeSwitcher'; export default function LandingPage() { const [mobileMenuOpen, setMobileMenuOpen] = useState(false); diff --git a/opensaas-sh/blog/src/content/docs/general/admin-dashboard.md b/opensaas-sh/blog/src/content/docs/general/admin-dashboard.md index f5864a6..e926faf 100644 --- a/opensaas-sh/blog/src/content/docs/general/admin-dashboard.md +++ b/opensaas-sh/blog/src/content/docs/general/admin-dashboard.md @@ -20,8 +20,7 @@ entity User {=psl //... ``` -To give yourself administrator priveledges, make sure you add your email addresses to the `ADMIN_EMAILS` environment variable in `.env.server` file before registering/logging in with that email address. - +To give yourself administrator priveledges, make sure you add your email addresses to the `ADMIN_EMAILS` environment variable in `.env.server` file before registering/logging in with that email address: ```sh title=".env.server" ADMIN_EMAILS=me@example.com @@ -30,13 +29,12 @@ ADMIN_EMAILS=me@example.com ADMIN_EMAILS=me@example.com,you@example.com,them@example.com ``` -if you've already logged in with an email address that you want to give admin priveledges to, you can run the following command in a separate terminal window to update the user's `isAdmin` field: +Or if you've already logged in with an email address that you want to give admin priveledges to, you can run the following command in a separate terminal window to update the user's `isAdmin` field manually: ```sh wasp db studio ``` - ![db studio](/stripe/db-studio.png) --- @@ -49,8 +47,8 @@ If you're finding this template and its guides useful, consider giving us [a sta ## Admin Dashboard Pages -### Dashboard -The Admin dashboard is a single place for you to view your most important metrics and perform some admin tasks. At the moment, it pulls data from: +### Analytics Dashboard +The Admin analytics dashboard is a single place for you to view your most important metrics and perform some admin tasks. At the moment, it pulls data from: @@ -67,7 +65,23 @@ The Admin dashboard is a single place for you to view your most important metric - total number of paying users - daily change in number of paying users -For a guide on how to integrate these services, check out the [Stripe](/guides/stripe-integration) and [Analytics guide](/guides/analytics) of the docs. +These metrics are aggregated within the background job `dailyStatsJob`, which by default is run every hour. You can change the frequency of this job by modifying its `cron` field: + +```ts title="main.wasp" {8,7} +job dailyStatsJob { + executor: PgBoss, + perform: { + fn: import { calculateDailyStats } from "@src/analytics/stats" + }, + schedule: { + cron: "0 * * * *" // every hour. useful in production + // cron: "* * * * *" // every minute. useful for debugging + }, + entities: [User, DailyStats, Logs, PageViewSource] +} +``` + +For a guide on how to integrate these services so that you can view your analytics via the dashboard, check out the [Stripe](/guides/stripe-integration) and [Analytics guide](/guides/analytics) of the docs. :::note[Help us improve] We're always looking to improve the Admin dashboard. If you feel something is missing or could be improved, consider [opening an issue](https://github.com/wasp-lang/open-saas/issues) or [submitting a pull request](https://github.com/wasp-lang/open-saas/pulls) @@ -77,4 +91,4 @@ We're always looking to improve the Admin dashboard. If you feel something is mi The Users page is where you can view all your users and their most important details. You can also search and filter users by: - email address - subscription/payment status - +- admin status diff --git a/opensaas-sh/blog/src/content/docs/guides/analytics.md b/opensaas-sh/blog/src/content/docs/guides/analytics.md index a729c73..f873868 100644 --- a/opensaas-sh/blog/src/content/docs/guides/analytics.md +++ b/opensaas-sh/blog/src/content/docs/guides/analytics.md @@ -63,7 +63,7 @@ After you sign up for [Google analytics](https://analytics.google.com/), go to y Once you've completed the steps to create a new Property, some Installation Instructions will pop up. Select `install manually` where you should see a string that looks like this: -```sh "" +```sh title="" https://www.googletagmanager.com/gtag/js?id= ``` and copy and paste the Google Analytics ID into your `.env.client` file to get it working with the [Cookie Consent Modal](./cookie-consent.md) provided with this template: diff --git a/template/app/main.wasp b/template/app/main.wasp index b5e0f92..0f81d0e 100644 --- a/template/app/main.wasp +++ b/template/app/main.wasp @@ -108,55 +108,6 @@ entity Task {=psl isDone Boolean @default(false) psl=} -// TODO: add functionality to allow users to send messages to admin -// and make them accessible via the admin dashboard -entity ContactFormMessage {=psl - id String @id @default(uuid()) - createdAt DateTime @default(now()) - - user User @relation(fields: [userId], references: [id]) - userId String - - content String - isRead Boolean @default(false) - repliedAt DateTime? -psl=} - -entity DailyStats {=psl - id Int @id @default(autoincrement()) - date DateTime @default(now()) @unique - - totalViews Int @default(0) - prevDayViewsChangePercent String @default("0") - userCount Int @default(0) - paidUserCount Int @default(0) - userDelta Int @default(0) - paidUserDelta Int @default(0) - totalRevenue Float @default(0) - totalProfit Float @default(0) - - sources PageViewSource[] -psl=} - -entity PageViewSource {=psl - @@id([date, name]) - name String - date DateTime @default(now()) - - dailyStats DailyStats? @relation(fields: [dailyStatsId], references: [id]) - dailyStatsId Int? - - visitors Int -psl=} - -entity Logs {=psl - id Int @id @default(autoincrement()) - createdAt DateTime @default(now()) - - message String - level String -psl=} - route LandingPageRoute { path: "/", to: LandingPage } page LandingPage { component: import LandingPage from "@src/client/landing-page/LandingPage" @@ -195,68 +146,6 @@ page DemoAppPage { component: import DemoAppPage from "@src/client/app/DemoAppPage" } -//#region Admin Pages -route AdminRoute { path: "/admin", to: DashboardPage } -page DashboardPage { - authRequired: true, - component: import Dashboard from "@src/client/admin/pages/DashboardPage" -} - -route AdminUsersRoute { path: "/admin/users", to: AdminUsersPage } -page AdminUsersPage { - authRequired: true, - component: import AdminUsers from "@src/client/admin/pages/Users" -} - -route AdminSettingsRoute { path: "/admin/settings", to: AdminSettingsPage } -page AdminSettingsPage { - authRequired: true, - component: import AdminSettings from "@src/client/admin/pages/Settings" -} - -route AdminChartsRoute { path: "/admin/chart", to: AdminChartsPage } -page AdminChartsPage { - authRequired: true, - component: import AdminCharts from "@src/client/admin/pages/Chart" -} - -route AdminMessagesRoute { path: "/admin/messages", to: AdminMessagesPage } -page AdminMessagesPage { - authRequired: true, - component: import AdminMessages from "@src/client/admin/pages/Messages" -} - -route AdminFormElementsRoute { path: "/admin/forms/form-elements", to: AdminFormElementsPage } -page AdminFormElementsPage { - authRequired: true, - component: import AdminForms from "@src/client/admin/pages/Form/FormElements" -} - -route AdminFormLayoutsRoute { path: "/admin/forms/form-layouts", to: AdminFormLayoutsPage } -page AdminFormLayoutsPage { - authRequired: true, - component: import AdminForms from "@src/client/admin/pages/Form/FormLayout" -} - -route AdminCalendarRoute { path: "/admin/calendar", to: AdminCalendarPage } -page AdminCalendarPage { - authRequired: true, - component: import AdminCalendar from "@src/client/admin/pages/Calendar" -} - -route AdminUIAlertsRoute { path: "/admin/ui/alerts", to: AdminUIAlertsPage } -page AdminUIAlertsPage { - authRequired: true, - component: import AdminUI from "@src/client/admin/pages/UiElements/Alerts" -} - -route AdminUIButtonsRoute { path: "/admin/ui/buttons", to: AdminUIButtonsPage } -page AdminUIButtonsPage { - authRequired: true, - component: import AdminUI from "@src/client/admin/pages/UiElements/Buttons" -} -//#endregion - action generateGptResponse { fn: import { generateGptResponse } from "@src/server/actions.js", entities: [User, Task, GptResponse] @@ -287,11 +176,6 @@ query getAllTasksByUser { entities: [Task] } -query getDailyStats { - fn: import { getDailyStats } from "@src/server/queries.js", - entities: [User, DailyStats] -} - job emailChecker { executor: PgBoss, perform: { @@ -303,18 +187,6 @@ job emailChecker { entities: [User] } -job dailyStatsJob { - executor: PgBoss, - perform: { - fn: import { calculateDailyStats } from "@src/server/workers/calculateDailyStats.js" - }, - schedule: { - cron: "0 * * * *" // every hour. useful in production - // cron: "* * * * *" // every minute. useful for debugging - }, - entities: [User, DailyStats, Logs, PageViewSource] -} - //#region User entity User {=psl id String @id @default(uuid()) @@ -421,3 +293,136 @@ entity File {=psl uploadUrl String psl=} //#endregion + +//#region Analytics +query getDailyStats { + fn: import { getDailyStats } from "@src/analytics/operations", + entities: [User, DailyStats] +} + +job dailyStatsJob { + executor: PgBoss, + perform: { + fn: import { calculateDailyStats } from "@src/analytics/stats" + }, + schedule: { + cron: "0 * * * *" // every hour. useful in production + // cron: "* * * * *" // every minute. useful for debugging + }, + entities: [User, DailyStats, Logs, PageViewSource] +} + +entity DailyStats {=psl + id Int @id @default(autoincrement()) + date DateTime @default(now()) @unique + + totalViews Int @default(0) + prevDayViewsChangePercent String @default("0") + userCount Int @default(0) + paidUserCount Int @default(0) + userDelta Int @default(0) + paidUserDelta Int @default(0) + totalRevenue Float @default(0) + totalProfit Float @default(0) + + sources PageViewSource[] +psl=} + +entity PageViewSource {=psl + @@id([date, name]) + name String + date DateTime @default(now()) + + dailyStats DailyStats? @relation(fields: [dailyStatsId], references: [id]) + dailyStatsId Int? + + visitors Int +psl=} + +entity Logs {=psl + id Int @id @default(autoincrement()) + createdAt DateTime @default(now()) + + message String + level String +psl=} +//#endregion + +//#region Admin Dashboard +route AdminRoute { path: "/admin", to: AnalyticsDashboardPage } +page AnalyticsDashboardPage { + authRequired: true, + component: import AnalyticsDashboardPage from "@src/admin/dashboards/analytics/AnalyticsDashboardPage" +} + +route AdminUsersRoute { path: "/admin/users", to: AdminUsersPage } +page AdminUsersPage { + authRequired: true, + component: import AdminUsers from "@src/admin/dashboards/users/UsersDashboardPage" +} + +route AdminSettingsRoute { path: "/admin/settings", to: AdminSettingsPage } +page AdminSettingsPage { + authRequired: true, + component: import AdminSettings from "@src/admin/elements/settings/SettingsPage" +} + +route AdminChartsRoute { path: "/admin/chart", to: AdminChartsPage } +page AdminChartsPage { + authRequired: true, + component: import AdminCharts from "@src/admin/elements/charts/ChartsPage" +} + +route AdminFormElementsRoute { path: "/admin/forms/form-elements", to: AdminFormElementsPage } +page AdminFormElementsPage { + authRequired: true, + component: import AdminForms from "@src/admin/elements/forms/FormElementsPage" +} + +route AdminFormLayoutsRoute { path: "/admin/forms/form-layouts", to: AdminFormLayoutsPage } +page AdminFormLayoutsPage { + authRequired: true, + component: import AdminForms from "@src/admin/elements/forms/FormLayoutsPage" +} + +route AdminCalendarRoute { path: "/admin/calendar", to: AdminCalendarPage } +page AdminCalendarPage { + authRequired: true, + component: import AdminCalendar from "@src/admin/elements/calendar/CalendarPage" +} + +route AdminUIAlertsRoute { path: "/admin/ui/alerts", to: AdminUIAlertsPage } +page AdminUIAlertsPage { + authRequired: true, + component: import AdminUI from "@src/admin/elements/ui-elements/AlertsPage" +} + +route AdminUIButtonsRoute { path: "/admin/ui/buttons", to: AdminUIButtonsPage } +page AdminUIButtonsPage { + authRequired: true, + component: import AdminUI from "@src/admin/elements/ui-elements/ButtonsPage" +} +//#endregion + +//#region Contact Form Messages +// TODO: +// add functionality to allow users to send messages to admin +// and make them accessible via the admin dashboard +route AdminMessagesRoute { path: "/admin/messages", to: AdminMessagesPage } +page AdminMessagesPage { + authRequired: true, + component: import AdminMessages from "@src/messages/MessagesPage" +} + +entity ContactFormMessage {=psl + id String @id @default(uuid()) + createdAt DateTime @default(now()) + + user User @relation(fields: [userId], references: [id]) + userId String + + content String + isRead Boolean @default(false) + repliedAt DateTime? +psl=} +//#endregion diff --git a/template/app/src/client/admin/pages/DashboardPage.tsx b/template/app/src/admin/dashboards/analytics/AnalyticsDashboardPage.tsx similarity index 75% rename from template/app/src/client/admin/pages/DashboardPage.tsx rename to template/app/src/admin/dashboards/analytics/AnalyticsDashboardPage.tsx index 25882c8..6f89ae5 100644 --- a/template/app/src/client/admin/pages/DashboardPage.tsx +++ b/template/app/src/admin/dashboards/analytics/AnalyticsDashboardPage.tsx @@ -1,12 +1,12 @@ import { type User } from 'wasp/entities'; import { useQuery, getDailyStats } from 'wasp/client/operations'; -import TotalSignupsCard from '../components/TotalSignupsCard'; -import TotalPageViewsCard from '../components/TotalPaidViewsCard'; -import TotalPayingUsersCard from '../components/TotalPayingUsersCard'; -import TotalRevenueCard from '../components/TotalRevenueCard'; -import RevenueAndProfitChart from '../components/RevenueAndProfitChart'; -import SourcesTable from '../components/SourcesTable'; -import DefaultLayout from '../layout/DefaultLayout'; +import TotalSignupsCard from './TotalSignupsCard'; +import TotalPageViewsCard from './TotalPageViewsCard'; +import TotalPayingUsersCard from './TotalPayingUsersCard'; +import TotalRevenueCard from './TotalRevenueCard'; +import RevenueAndProfitChart from './RevenueAndProfitChart'; +import SourcesTable from './PageViewSourcesTable'; +import DefaultLayout from '../../layout/DefaultLayout'; import { useHistory } from 'react-router-dom'; const Dashboard = ({ user }: { user: User }) => { diff --git a/template/app/src/client/admin/components/SourcesTable.tsx b/template/app/src/admin/dashboards/analytics/PageViewSourcesTable.tsx similarity index 93% rename from template/app/src/client/admin/components/SourcesTable.tsx rename to template/app/src/admin/dashboards/analytics/PageViewSourcesTable.tsx index c05f5ba..493d214 100644 --- a/template/app/src/client/admin/components/SourcesTable.tsx +++ b/template/app/src/admin/dashboards/analytics/PageViewSourcesTable.tsx @@ -1,6 +1,6 @@ import { type PageViewSource } from 'wasp/entities'; -const SourcesTable = ({ sources }: { sources: PageViewSource[] | undefined }) => { +const PageViewSourcesTable = ({ sources }: { sources: PageViewSource[] | undefined }) => { return (

Top Sources

@@ -44,4 +44,4 @@ const SourcesTable = ({ sources }: { sources: PageViewSource[] | undefined }) => ); }; -export default SourcesTable; +export default PageViewSourcesTable; diff --git a/template/app/src/client/admin/components/RevenueAndProfitChart.tsx b/template/app/src/admin/dashboards/analytics/RevenueAndProfitChart.tsx similarity index 99% rename from template/app/src/client/admin/components/RevenueAndProfitChart.tsx rename to template/app/src/admin/dashboards/analytics/RevenueAndProfitChart.tsx index 2cc70ef..dca3f54 100644 --- a/template/app/src/client/admin/components/RevenueAndProfitChart.tsx +++ b/template/app/src/admin/dashboards/analytics/RevenueAndProfitChart.tsx @@ -1,7 +1,7 @@ import { ApexOptions } from 'apexcharts'; import React, { useState, useMemo, useEffect } from 'react'; import ReactApexChart from 'react-apexcharts'; -import { DailyStatsProps } from '../common/types'; +import { type DailyStatsProps } from '../../../analytics/stats'; const options: ApexOptions = { legend: { diff --git a/template/app/src/client/admin/components/TotalPaidViewsCard.tsx b/template/app/src/admin/dashboards/analytics/TotalPageViewsCard.tsx similarity index 95% rename from template/app/src/client/admin/components/TotalPaidViewsCard.tsx rename to template/app/src/admin/dashboards/analytics/TotalPageViewsCard.tsx index e35d98c..3322929 100644 --- a/template/app/src/client/admin/components/TotalPaidViewsCard.tsx +++ b/template/app/src/admin/dashboards/analytics/TotalPageViewsCard.tsx @@ -1,5 +1,5 @@ -import { cn } from '../../cn'; -import { UpArrow, DownArrow } from '../images/icon/icons-arrows'; +import { cn } from '../../../client/cn'; +import { UpArrow, DownArrow } from '../../../client/icons/icons-arrows'; type PageViewsStats = { totalPageViews: number | undefined; diff --git a/template/app/src/client/admin/components/TotalPayingUsersCard.tsx b/template/app/src/admin/dashboards/analytics/TotalPayingUsersCard.tsx similarity index 94% rename from template/app/src/client/admin/components/TotalPayingUsersCard.tsx rename to template/app/src/admin/dashboards/analytics/TotalPayingUsersCard.tsx index edd1d35..ecb2984 100644 --- a/template/app/src/client/admin/components/TotalPayingUsersCard.tsx +++ b/template/app/src/admin/dashboards/analytics/TotalPayingUsersCard.tsx @@ -1,7 +1,7 @@ import { useMemo } from 'react'; -import { UpArrow, DownArrow } from '../images/icon/icons-arrows'; -import type { DailyStatsProps } from '../common/types'; -import { cn } from '../../cn'; +import { cn } from '../../../client/cn'; +import { UpArrow, DownArrow } from '../../../client/icons/icons-arrows'; +import { type DailyStatsProps } from '../../../analytics/stats'; const TotalPayingUsersCard = ({ dailyStats, isLoading }: DailyStatsProps) => { const isDeltaPositive = useMemo(() => { diff --git a/template/app/src/client/admin/components/TotalRevenueCard.tsx b/template/app/src/admin/dashboards/analytics/TotalRevenueCard.tsx similarity index 96% rename from template/app/src/client/admin/components/TotalRevenueCard.tsx rename to template/app/src/admin/dashboards/analytics/TotalRevenueCard.tsx index 9198190..1d3faf0 100644 --- a/template/app/src/client/admin/components/TotalRevenueCard.tsx +++ b/template/app/src/admin/dashboards/analytics/TotalRevenueCard.tsx @@ -1,6 +1,6 @@ import { useMemo } from 'react'; -import { UpArrow, DownArrow } from '../images/icon/icons-arrows'; -import type { DailyStatsProps } from '../common/types'; +import { UpArrow, DownArrow } from '../../../client/icons/icons-arrows'; +import { type DailyStatsProps } from '../../../analytics/stats'; const TotalRevenueCard = ({dailyStats, weeklyStats, isLoading}: DailyStatsProps) => { const isDeltaPositive = useMemo(() => { diff --git a/template/app/src/client/admin/components/TotalSignupsCard.tsx b/template/app/src/admin/dashboards/analytics/TotalSignupsCard.tsx similarity index 94% rename from template/app/src/client/admin/components/TotalSignupsCard.tsx rename to template/app/src/admin/dashboards/analytics/TotalSignupsCard.tsx index db4b4bb..f497216 100644 --- a/template/app/src/client/admin/components/TotalSignupsCard.tsx +++ b/template/app/src/admin/dashboards/analytics/TotalSignupsCard.tsx @@ -1,7 +1,7 @@ import { useMemo } from 'react'; -import { UpArrow } from '../images/icon/icons-arrows'; -import type { DailyStatsProps } from '../common/types'; -import { cn } from '../../cn'; +import { cn } from '../../../client/cn'; +import { UpArrow } from '../../../client/icons/icons-arrows'; +import { type DailyStatsProps } from '../../../analytics/stats'; const TotalSignupsCard = ({ dailyStats, isLoading }: DailyStatsProps) => { const isDeltaPositive = useMemo(() => { diff --git a/template/app/src/client/admin/components/DropdownEditDelete.tsx b/template/app/src/admin/dashboards/users/DropdownEditDelete.tsx similarity index 99% rename from template/app/src/client/admin/components/DropdownEditDelete.tsx rename to template/app/src/admin/dashboards/users/DropdownEditDelete.tsx index 0f9a0d6..84dab38 100644 --- a/template/app/src/client/admin/components/DropdownEditDelete.tsx +++ b/template/app/src/admin/dashboards/users/DropdownEditDelete.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react'; -import { cn } from '../../cn'; +import { cn } from '../../../client/cn'; const DropdownDefault = () => { const [dropdownOpen, setDropdownOpen] = useState(false); diff --git a/template/app/src/client/admin/components/SwitcherOne.tsx b/template/app/src/admin/dashboards/users/SwitcherOne.tsx similarity index 96% rename from template/app/src/client/admin/components/SwitcherOne.tsx rename to template/app/src/admin/dashboards/users/SwitcherOne.tsx index c4451d9..6721194 100644 --- a/template/app/src/client/admin/components/SwitcherOne.tsx +++ b/template/app/src/admin/dashboards/users/SwitcherOne.tsx @@ -1,6 +1,6 @@ import { type User } from 'wasp/entities'; import { useState } from 'react'; -import { cn } from '../../cn'; +import { cn } from '../../../client/cn'; const SwitcherOne = ({ user, updateUserById }: { user?: Partial; updateUserById?: any }) => { const [enabled, setEnabled] = useState(user?.isAdmin || false); diff --git a/template/app/src/admin/dashboards/users/UsersDashboardPage.tsx b/template/app/src/admin/dashboards/users/UsersDashboardPage.tsx new file mode 100644 index 0000000..199f433 --- /dev/null +++ b/template/app/src/admin/dashboards/users/UsersDashboardPage.tsx @@ -0,0 +1,16 @@ +import UsersTable from './UsersTable'; +import Breadcrumb from '../../layout/Breadcrumb'; +import DefaultLayout from '../../layout/DefaultLayout'; + +const Users = () => { + return ( + + +
+ +
+
+ ); +}; + +export default Users; diff --git a/template/app/src/client/admin/components/UsersTable.tsx b/template/app/src/admin/dashboards/users/UsersTable.tsx similarity index 99% rename from template/app/src/client/admin/components/UsersTable.tsx rename to template/app/src/admin/dashboards/users/UsersTable.tsx index e005a10..1cbe9e1 100644 --- a/template/app/src/client/admin/components/UsersTable.tsx +++ b/template/app/src/admin/dashboards/users/UsersTable.tsx @@ -1,9 +1,9 @@ +import { type SubscriptionStatus } from '../../../payment/plans'; import { updateUserById, useQuery, getPaginatedUsers } from 'wasp/client/operations'; import { useState, useEffect } from 'react'; import SwitcherOne from './SwitcherOne'; -import Loader from '../common/Loader'; +import LoadingSpinner from '../../layout/LoadingSpinner'; import DropdownEditDelete from './DropdownEditDelete'; -import { type SubscriptionStatus } from '../../../payment/plans'; const UsersTable = () => { const [skip, setskip] = useState(0); @@ -188,7 +188,7 @@ const UsersTable = () => {
{isLoading && (
- +
)} {!!data?.users && diff --git a/template/app/src/client/admin/pages/Calendar.tsx b/template/app/src/admin/elements/calendar/CalendarPage.tsx similarity index 99% rename from template/app/src/client/admin/pages/Calendar.tsx rename to template/app/src/admin/elements/calendar/CalendarPage.tsx index 41e056a..3e6a655 100644 --- a/template/app/src/client/admin/pages/Calendar.tsx +++ b/template/app/src/admin/elements/calendar/CalendarPage.tsx @@ -1,5 +1,5 @@ -import Breadcrumb from '../components/Breadcrumb'; -import DefaultLayout from '../layout/DefaultLayout'; +import Breadcrumb from '../../layout/Breadcrumb'; +import DefaultLayout from '../../layout/DefaultLayout'; const Calendar = () => { return ( diff --git a/template/app/src/client/admin/components/BarChart.tsx b/template/app/src/admin/elements/charts/BarChart.tsx similarity index 100% rename from template/app/src/client/admin/components/BarChart.tsx rename to template/app/src/admin/elements/charts/BarChart.tsx diff --git a/template/app/src/admin/elements/charts/ChartsPage.tsx b/template/app/src/admin/elements/charts/ChartsPage.tsx new file mode 100644 index 0000000..93b0efd --- /dev/null +++ b/template/app/src/admin/elements/charts/ChartsPage.tsx @@ -0,0 +1,23 @@ +import Breadcrumb from '../../layout/Breadcrumb'; +import DefaultLayout from '../../layout/DefaultLayout'; +import BarChart from './BarChart'; +import PieChart from './PieChart'; +import DataStats from './DataStatsChart'; + +const Chart = () => { + return ( + + + +
+ +
+ +
+ +
+
+ ); +}; + +export default Chart; diff --git a/template/app/src/client/admin/components/DataStats.tsx b/template/app/src/admin/elements/charts/DataStatsChart.tsx similarity index 98% rename from template/app/src/client/admin/components/DataStats.tsx rename to template/app/src/admin/elements/charts/DataStatsChart.tsx index 73910ad..a1b3882 100644 --- a/template/app/src/client/admin/components/DataStats.tsx +++ b/template/app/src/admin/elements/charts/DataStatsChart.tsx @@ -1,11 +1,11 @@ -const DataStats = () => { +const DataStatsChart = () => { return (

- $4,350 + 4,350

Unique Visitors

@@ -99,4 +99,4 @@ const DataStats = () => { ); }; -export default DataStats; +export default DataStatsChart; diff --git a/template/app/src/client/admin/components/PieChart.tsx b/template/app/src/admin/elements/charts/PieChart.tsx similarity index 100% rename from template/app/src/client/admin/components/PieChart.tsx rename to template/app/src/admin/elements/charts/PieChart.tsx diff --git a/template/app/src/client/admin/components/CheckboxOne.tsx b/template/app/src/admin/elements/forms/CheckboxOne.tsx similarity index 96% rename from template/app/src/client/admin/components/CheckboxOne.tsx rename to template/app/src/admin/elements/forms/CheckboxOne.tsx index 5b9da03..3136eb8 100644 --- a/template/app/src/client/admin/components/CheckboxOne.tsx +++ b/template/app/src/admin/elements/forms/CheckboxOne.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { cn } from '../../cn'; +import { cn } from '../../../client/cn'; const CheckboxOne = () => { const [isChecked, setIsChecked] = useState(false); diff --git a/template/app/src/client/admin/components/CheckboxTwo.tsx b/template/app/src/admin/elements/forms/CheckboxTwo.tsx similarity index 97% rename from template/app/src/client/admin/components/CheckboxTwo.tsx rename to template/app/src/admin/elements/forms/CheckboxTwo.tsx index a5e24ac..f9b4206 100644 --- a/template/app/src/client/admin/components/CheckboxTwo.tsx +++ b/template/app/src/admin/elements/forms/CheckboxTwo.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { cn } from '../../cn'; +import { cn } from '../../../client/cn'; const CheckboxTwo = () => { const [enabled, setEnabled] = useState(false); diff --git a/template/app/src/admin/elements/forms/FormElementsPage.tsx b/template/app/src/admin/elements/forms/FormElementsPage.tsx new file mode 100644 index 0000000..c5d76a3 --- /dev/null +++ b/template/app/src/admin/elements/forms/FormElementsPage.tsx @@ -0,0 +1,271 @@ +import Breadcrumb from '../../layout/Breadcrumb'; +import DefaultLayout from '../../layout/DefaultLayout'; +import CheckboxOne from './CheckboxOne'; +import SwitcherOne from '../../dashboards/users/SwitcherOne'; +import SwitcherTwo from './SwitcherTwo'; + +const FormElements = () => { + return ( + + + +
+
+ {/* */} +
+
+

Input Fields

+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + {/* */} +
+
+

Toggle switch input

+
+
+ + +
+
+ + {/* */} +
+
+

Time and date

+
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+
+
+ + {/* */} +
+
+

File upload

+
+
+
+ + +
+ +
+ + +
+
+
+
+ +
+ {/* */} +
+
+

Textarea Fields

+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + {/* */} +
+
+

Checkbox and radio

+
+
+ +
+
+ + {/* */} +
+
+

Select input

+
+
+
+ +
+ + + + + + + + + + + + + + + + + +
+
+ +
+ +
+
+ + Design + + + + + + + + Development + + + + + + +
+ + + + + + + + +
+
+
+
+
+
+
+ ); +}; + +export default FormElements; diff --git a/template/app/src/admin/elements/forms/FormLayoutsPage.tsx b/template/app/src/admin/elements/forms/FormLayoutsPage.tsx new file mode 100644 index 0000000..28dd2da --- /dev/null +++ b/template/app/src/admin/elements/forms/FormLayoutsPage.tsx @@ -0,0 +1,226 @@ +import Breadcrumb from '../../layout/Breadcrumb'; +import DefaultLayout from '../../layout/DefaultLayout'; + +const FormLayout = () => { + return ( + + + +
+
+ {/* */} +
+
+

Contact Form

+
+
+
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + + + + + + + +
+
+ +
+ + +
+ + +
+
+
+
+ +
+ {/* */} +
+
+

Sign In Form

+
+
+
+
+ + +
+ +
+ + +
+ +
+ + + + Forget password? + +
+ + +
+
+
+ + {/* */} +
+
+

Sign Up Form

+
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+
+
+
+
+
+ ); +}; + +export default FormLayout; diff --git a/template/app/src/client/admin/components/SwitcherTwo.tsx b/template/app/src/admin/elements/forms/SwitcherTwo.tsx similarity index 98% rename from template/app/src/client/admin/components/SwitcherTwo.tsx rename to template/app/src/admin/elements/forms/SwitcherTwo.tsx index 5456fe5..55fcbd9 100644 --- a/template/app/src/client/admin/components/SwitcherTwo.tsx +++ b/template/app/src/admin/elements/forms/SwitcherTwo.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { cn } from '../../cn'; +import { cn } from '../../../client/cn'; const SwitcherTwo = () => { const [enabled, setEnabled] = useState(false); diff --git a/template/app/src/client/admin/pages/Settings.tsx b/template/app/src/admin/elements/settings/SettingsPage.tsx similarity index 99% rename from template/app/src/client/admin/pages/Settings.tsx rename to template/app/src/admin/elements/settings/SettingsPage.tsx index 6297334..4a20fcc 100644 --- a/template/app/src/client/admin/pages/Settings.tsx +++ b/template/app/src/admin/elements/settings/SettingsPage.tsx @@ -1,9 +1,9 @@ import { FormEvent } from 'react'; -import Breadcrumb from '../components/Breadcrumb'; import toast from 'react-hot-toast'; -import DefaultLayout from '../layout/DefaultLayout'; +import Breadcrumb from '../../layout/Breadcrumb'; +import DefaultLayout from '../../layout/DefaultLayout'; -const Settings = () => { +const SettingsPage = () => { const handleSubmit = (event: FormEvent) => { // TODO add toast provider / wrapper event.preventDefault(); @@ -322,4 +322,4 @@ const Settings = () => { ); }; -export default Settings; +export default SettingsPage; diff --git a/template/app/src/client/admin/pages/UiElements/Alerts.tsx b/template/app/src/admin/elements/ui-elements/AlertsPage.tsx similarity index 51% rename from template/app/src/client/admin/pages/UiElements/Alerts.tsx rename to template/app/src/admin/elements/ui-elements/AlertsPage.tsx index e3e7eed..6718440 100644 --- a/template/app/src/client/admin/pages/UiElements/Alerts.tsx +++ b/template/app/src/admin/elements/ui-elements/AlertsPage.tsx @@ -1,92 +1,64 @@ -import Breadcrumb from '../../components/Breadcrumb'; +import Breadcrumb from '../../layout/Breadcrumb'; import DefaultLayout from '../../layout/DefaultLayout'; const Alerts = () => { return ( - + -
-
+
+
{/* */} -
-
- +
+
+
-
-
- Attention needed -
-

- Lorem Ipsum is simply dummy text of the printing and typesetting - industry. Lorem Ipsum has been the industry's standard dummy - text ever since the 1500s, when +

+
Attention needed
+

+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the + industry's standard dummy text ever since the 1500s, when

{/* */} -
-
- +
+
+
-
-
- Message Sent Successfully -
-

- Lorem Ipsum is simply dummy text of the printing and typesetting - industry. +

+
Message Sent Successfully
+

+ Lorem Ipsum is simply dummy text of the printing and typesetting industry.

{/* */} -
-
- +
+
+
-
-
- There were 1 errors with your submission -
+
+
There were 1 errors with your submission
    -
  • - Lorem Ipsum is simply dummy text of the printing -
  • +
  • Lorem Ipsum is simply dummy text of the printing
diff --git a/template/app/src/client/admin/pages/UiElements/Buttons.tsx b/template/app/src/admin/elements/ui-elements/ButtonsPage.tsx similarity index 99% rename from template/app/src/client/admin/pages/UiElements/Buttons.tsx rename to template/app/src/admin/elements/ui-elements/ButtonsPage.tsx index c1402f9..6d607d5 100644 --- a/template/app/src/client/admin/pages/UiElements/Buttons.tsx +++ b/template/app/src/admin/elements/ui-elements/ButtonsPage.tsx @@ -1,5 +1,5 @@ import { Link } from 'react-router-dom'; -import Breadcrumb from '../../components/Breadcrumb'; +import Breadcrumb from '../../layout/Breadcrumb'; import DefaultLayout from '../../layout/DefaultLayout'; const Buttons = () => { diff --git a/template/app/src/client/admin/components/Breadcrumb.tsx b/template/app/src/admin/layout/Breadcrumb.tsx similarity index 100% rename from template/app/src/client/admin/components/Breadcrumb.tsx rename to template/app/src/admin/layout/Breadcrumb.tsx diff --git a/template/app/src/client/admin/layout/DefaultLayout.tsx b/template/app/src/admin/layout/DefaultLayout.tsx similarity index 94% rename from template/app/src/client/admin/layout/DefaultLayout.tsx rename to template/app/src/admin/layout/DefaultLayout.tsx index 3495da0..056abaa 100644 --- a/template/app/src/client/admin/layout/DefaultLayout.tsx +++ b/template/app/src/admin/layout/DefaultLayout.tsx @@ -1,7 +1,7 @@ import { useAuth } from 'wasp/client/auth'; import { useState, ReactNode, FC } from 'react'; -import Header from '../components/Header'; -import Sidebar from '../components/Sidebar'; +import Header from './Header'; +import Sidebar from './Sidebar'; interface Props { children?: ReactNode; diff --git a/template/app/src/client/admin/components/Header.tsx b/template/app/src/admin/layout/Header.tsx similarity index 94% rename from template/app/src/client/admin/components/Header.tsx rename to template/app/src/admin/layout/Header.tsx index f094625..88a0cb2 100644 --- a/template/app/src/client/admin/components/Header.tsx +++ b/template/app/src/admin/layout/Header.tsx @@ -1,8 +1,8 @@ import { type AuthUser } from 'wasp/auth/types'; -import DarkModeSwitcher from './DarkModeSwitcher'; -import MessageButton from './MessageButton'; -import DropdownUser from '../../../user/DropdownUser'; -import { cn } from '../../cn'; +import MessageButton from '../../messages/MessageButton'; +import DropdownUser from '../../user/DropdownUser'; +import { cn } from '../../client/cn'; +import DarkModeSwitcher from '../../client/components/DarkModeSwitcher'; const Header = (props: { sidebarOpen: string | boolean | undefined; diff --git a/template/app/src/client/admin/common/Loader/index.tsx b/template/app/src/admin/layout/LoadingSpinner.tsx similarity index 78% rename from template/app/src/client/admin/common/Loader/index.tsx rename to template/app/src/admin/layout/LoadingSpinner.tsx index 0915c82..7990079 100644 --- a/template/app/src/client/admin/common/Loader/index.tsx +++ b/template/app/src/admin/layout/LoadingSpinner.tsx @@ -1,4 +1,4 @@ -const Loader = () => { +const LoadingSpinner = () => { return (
@@ -6,4 +6,4 @@ const Loader = () => { ); }; -export default Loader; +export default LoadingSpinner; diff --git a/template/app/src/client/admin/components/Sidebar.tsx b/template/app/src/admin/layout/Sidebar.tsx similarity index 99% rename from template/app/src/client/admin/components/Sidebar.tsx rename to template/app/src/admin/layout/Sidebar.tsx index e55d537..e40f45d 100644 --- a/template/app/src/client/admin/components/Sidebar.tsx +++ b/template/app/src/admin/layout/Sidebar.tsx @@ -1,8 +1,8 @@ import React, { useEffect, useRef, useState } from 'react'; import { NavLink, useLocation } from 'react-router-dom'; -import Logo from '../../static/logo.png'; +import Logo from '../../client/static/logo.png'; import SidebarLinkGroup from './SidebarLinkGroup'; -import { cn } from '../../cn'; +import { cn } from '../../client/cn'; interface SidebarProps { sidebarOpen: boolean; diff --git a/template/app/src/client/admin/components/SidebarLinkGroup.tsx b/template/app/src/admin/layout/SidebarLinkGroup.tsx similarity index 100% rename from template/app/src/client/admin/components/SidebarLinkGroup.tsx rename to template/app/src/admin/layout/SidebarLinkGroup.tsx diff --git a/template/app/src/analytics/operations.ts b/template/app/src/analytics/operations.ts new file mode 100644 index 0000000..86479a7 --- /dev/null +++ b/template/app/src/analytics/operations.ts @@ -0,0 +1,38 @@ +import { type DailyStats, type PageViewSource } from 'wasp/entities'; +import { HttpError } from 'wasp/server'; +import { type GetDailyStats } from 'wasp/server/operations'; + +type DailyStatsWithSources = DailyStats & { + sources: PageViewSource[]; +}; + +type DailyStatsValues = { + dailyStats: DailyStatsWithSources; + weeklyStats: DailyStatsWithSources[]; +}; + +export const getDailyStats: GetDailyStats = async (_args, context) => { + if (!context.user?.isAdmin) { + throw new HttpError(401); + } + const dailyStats = await context.entities.DailyStats.findFirstOrThrow({ + orderBy: { + date: 'desc', + }, + include: { + sources: true, + }, + }); + + const weeklyStats = await context.entities.DailyStats.findMany({ + orderBy: { + date: 'desc', + }, + take: 7, + include: { + sources: true, + }, + }); + + return { dailyStats, weeklyStats }; +}; diff --git a/template/app/src/server/workers/googleAnalyticsUtils.ts b/template/app/src/analytics/providers/googleAnalyticsUtils.ts similarity index 100% rename from template/app/src/server/workers/googleAnalyticsUtils.ts rename to template/app/src/analytics/providers/googleAnalyticsUtils.ts diff --git a/template/app/src/server/workers/plausibleAnalyticsUtils.ts b/template/app/src/analytics/providers/plausibleAnalyticsUtils.ts similarity index 96% rename from template/app/src/server/workers/plausibleAnalyticsUtils.ts rename to template/app/src/analytics/providers/plausibleAnalyticsUtils.ts index 976da83..51da1a5 100644 --- a/template/app/src/server/workers/plausibleAnalyticsUtils.ts +++ b/template/app/src/analytics/providers/plausibleAnalyticsUtils.ts @@ -39,7 +39,10 @@ async function getTotalPageViews() { `${PLAUSIBLE_BASE_URL}/v1/stats/aggregate?site_id=${PLAUSIBLE_SITE_ID}&metrics=pageviews`, { method: 'GET', - headers: headers, + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${PLAUSIBLE_API_KEY}`, + }, } ); if (!response.ok) { diff --git a/template/app/src/server/workers/calculateDailyStats.ts b/template/app/src/analytics/stats.ts similarity index 91% rename from template/app/src/server/workers/calculateDailyStats.ts rename to template/app/src/analytics/stats.ts index 202c284..d166666 100644 --- a/template/app/src/server/workers/calculateDailyStats.ts +++ b/template/app/src/analytics/stats.ts @@ -1,8 +1,11 @@ +import { type DailyStats } from 'wasp/entities'; import { type DailyStatsJob } from 'wasp/server/jobs'; import Stripe from 'stripe'; -import { stripe } from '../../payment/stripe/stripeClient'; -import { getDailyPageViews, getSources } from './plausibleAnalyticsUtils.js'; -// import { getDailyPageViews, getSources } from './googleAnalyticsUtils.js'; +import { stripe } from '../payment/stripe/stripeClient' +import { getDailyPageViews, getSources } from './providers/plausibleAnalyticsUtils'; +// import { getDailyPageViews, getSources } from './providers/googleAnalyticsUtils; + +export type DailyStatsProps = { dailyStats?: DailyStats; weeklyStats?: DailyStats[]; isLoading?: boolean }; export const calculateDailyStats: DailyStatsJob = async (_args, context) => { const nowUTC = new Date(Date.now()); diff --git a/template/app/src/client/admin/common/types.ts b/template/app/src/client/admin/common/types.ts deleted file mode 100644 index 0df9973..0000000 --- a/template/app/src/client/admin/common/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { type DailyStats } from 'wasp/entities'; - -export type DailyStatsProps = { dailyStats?: DailyStats; weeklyStats?: DailyStats[]; isLoading?: boolean }; diff --git a/template/app/src/client/admin/pages/Chart.tsx b/template/app/src/client/admin/pages/Chart.tsx deleted file mode 100644 index e56ebca..0000000 --- a/template/app/src/client/admin/pages/Chart.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import Breadcrumb from '../components/Breadcrumb'; -import BarChart from '../components/BarChart'; -import PieChart from '../components/PieChart'; -import DataStats from '../components/DataStats'; -import DefaultLayout from '../layout/DefaultLayout'; - -const Chart = () => { - return ( - - - -
- -
- -
- -
-
- ); -}; - -export default Chart; diff --git a/template/app/src/client/admin/pages/Form/FormElements.tsx b/template/app/src/client/admin/pages/Form/FormElements.tsx deleted file mode 100644 index 0716981..0000000 --- a/template/app/src/client/admin/pages/Form/FormElements.tsx +++ /dev/null @@ -1,343 +0,0 @@ -import Breadcrumb from '../../components/Breadcrumb'; -import CheckboxOne from '../../components/CheckboxOne'; -import SwitcherOne from '../../components/SwitcherOne'; -import SwitcherTwo from '../../components/SwitcherTwo'; -import DefaultLayout from '../../layout/DefaultLayout'; - -const FormElements = () => { - return ( - - - -
-
- {/* */} -
-
-

- Input Fields -

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

- Toggle switch input -

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

- Time and date -

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

- File upload -

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

- Textarea Fields -

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

- Checkbox and radio -

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

- Select input -

-
-
-
- -
- - - - - - - - - - - - - - - - - -
-
- -
- -
-
- - Design - - - - - - - - Development - - - - - - -
- - - - - - - - -
-
-
-
-
-
-
- ); -}; - -export default FormElements; diff --git a/template/app/src/client/admin/pages/Form/FormLayout.tsx b/template/app/src/client/admin/pages/Form/FormLayout.tsx deleted file mode 100644 index 4f7a549..0000000 --- a/template/app/src/client/admin/pages/Form/FormLayout.tsx +++ /dev/null @@ -1,258 +0,0 @@ -import Breadcrumb from '../../components/Breadcrumb'; -import DefaultLayout from '../../layout/DefaultLayout'; - -const FormLayout = () => { - return ( - - - -
-
- {/* */} -
-
-

- Contact Form -

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

- Sign In Form -

-
-
-
-
- - -
- -
- - -
- -
- - - - Forget password? - -
- - -
-
-
- - {/* */} -
-
-

- Sign Up Form -

-
-
-
-
- - -
- -
- - -
- -
- - -
- -
- - -
- - -
-
-
-
-
-
- ); -}; - -export default FormLayout; diff --git a/template/app/src/client/admin/pages/Users.tsx b/template/app/src/client/admin/pages/Users.tsx deleted file mode 100644 index ed23bc4..0000000 --- a/template/app/src/client/admin/pages/Users.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import Breadcrumb from '../components/Breadcrumb'; -import UsersTable from '../components/UsersTable'; -import DefaultLayout from '../layout/DefaultLayout'; - -const Users = () => { - return ( - - -
- -
-
- ); -}; - -export default Users; diff --git a/template/app/src/client/components/AppNavBar.tsx b/template/app/src/client/components/AppNavBar.tsx index fd3dd45..291a43e 100644 --- a/template/app/src/client/components/AppNavBar.tsx +++ b/template/app/src/client/components/AppNavBar.tsx @@ -9,7 +9,7 @@ import logo from '../static/logo.png'; import DropdownUser from '../../user/DropdownUser'; import { UserMenuItems } from '../../user/UserMenuItems'; import { DocsUrl, BlogUrl } from '../../common'; -import DarkModeSwitcher from '../admin/components/DarkModeSwitcher'; +import DarkModeSwitcher from './DarkModeSwitcher'; const navigation = [ { name: 'AI Scheduler (Demo App)', href: routes.DemoAppRoute.build() }, diff --git a/template/app/src/client/admin/components/DarkModeSwitcher.tsx b/template/app/src/client/components/DarkModeSwitcher.tsx similarity index 98% rename from template/app/src/client/admin/components/DarkModeSwitcher.tsx rename to template/app/src/client/components/DarkModeSwitcher.tsx index c95d51c..4fe67ce 100644 --- a/template/app/src/client/admin/components/DarkModeSwitcher.tsx +++ b/template/app/src/client/components/DarkModeSwitcher.tsx @@ -1,5 +1,5 @@ -import { cn } from '../../cn'; -import useColorMode from '../../hooks/useColorMode'; +import { cn } from '../cn'; +import useColorMode from '../hooks/useColorMode'; const DarkModeSwitcher = () => { const [colorMode, setColorMode] = useColorMode(); diff --git a/template/app/src/client/admin/fonts/Satoshi-Black.eot b/template/app/src/client/fonts/Satoshi-Black.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Black.eot rename to template/app/src/client/fonts/Satoshi-Black.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-Black.ttf b/template/app/src/client/fonts/Satoshi-Black.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Black.ttf rename to template/app/src/client/fonts/Satoshi-Black.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-Black.woff b/template/app/src/client/fonts/Satoshi-Black.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Black.woff rename to template/app/src/client/fonts/Satoshi-Black.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-Black.woff2 b/template/app/src/client/fonts/Satoshi-Black.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Black.woff2 rename to template/app/src/client/fonts/Satoshi-Black.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-BlackItalic.eot b/template/app/src/client/fonts/Satoshi-BlackItalic.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-BlackItalic.eot rename to template/app/src/client/fonts/Satoshi-BlackItalic.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-BlackItalic.ttf b/template/app/src/client/fonts/Satoshi-BlackItalic.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-BlackItalic.ttf rename to template/app/src/client/fonts/Satoshi-BlackItalic.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-BlackItalic.woff b/template/app/src/client/fonts/Satoshi-BlackItalic.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-BlackItalic.woff rename to template/app/src/client/fonts/Satoshi-BlackItalic.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-BlackItalic.woff2 b/template/app/src/client/fonts/Satoshi-BlackItalic.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-BlackItalic.woff2 rename to template/app/src/client/fonts/Satoshi-BlackItalic.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-Bold.eot b/template/app/src/client/fonts/Satoshi-Bold.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Bold.eot rename to template/app/src/client/fonts/Satoshi-Bold.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-Bold.ttf b/template/app/src/client/fonts/Satoshi-Bold.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Bold.ttf rename to template/app/src/client/fonts/Satoshi-Bold.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-Bold.woff b/template/app/src/client/fonts/Satoshi-Bold.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Bold.woff rename to template/app/src/client/fonts/Satoshi-Bold.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-Bold.woff2 b/template/app/src/client/fonts/Satoshi-Bold.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Bold.woff2 rename to template/app/src/client/fonts/Satoshi-Bold.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-BoldItalic.eot b/template/app/src/client/fonts/Satoshi-BoldItalic.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-BoldItalic.eot rename to template/app/src/client/fonts/Satoshi-BoldItalic.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-BoldItalic.ttf b/template/app/src/client/fonts/Satoshi-BoldItalic.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-BoldItalic.ttf rename to template/app/src/client/fonts/Satoshi-BoldItalic.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-BoldItalic.woff b/template/app/src/client/fonts/Satoshi-BoldItalic.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-BoldItalic.woff rename to template/app/src/client/fonts/Satoshi-BoldItalic.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-BoldItalic.woff2 b/template/app/src/client/fonts/Satoshi-BoldItalic.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-BoldItalic.woff2 rename to template/app/src/client/fonts/Satoshi-BoldItalic.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-Italic.eot b/template/app/src/client/fonts/Satoshi-Italic.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Italic.eot rename to template/app/src/client/fonts/Satoshi-Italic.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-Italic.ttf b/template/app/src/client/fonts/Satoshi-Italic.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Italic.ttf rename to template/app/src/client/fonts/Satoshi-Italic.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-Italic.woff b/template/app/src/client/fonts/Satoshi-Italic.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Italic.woff rename to template/app/src/client/fonts/Satoshi-Italic.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-Italic.woff2 b/template/app/src/client/fonts/Satoshi-Italic.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Italic.woff2 rename to template/app/src/client/fonts/Satoshi-Italic.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-Light.eot b/template/app/src/client/fonts/Satoshi-Light.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Light.eot rename to template/app/src/client/fonts/Satoshi-Light.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-Light.ttf b/template/app/src/client/fonts/Satoshi-Light.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Light.ttf rename to template/app/src/client/fonts/Satoshi-Light.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-Light.woff b/template/app/src/client/fonts/Satoshi-Light.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Light.woff rename to template/app/src/client/fonts/Satoshi-Light.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-Light.woff2 b/template/app/src/client/fonts/Satoshi-Light.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Light.woff2 rename to template/app/src/client/fonts/Satoshi-Light.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-LightItalic.eot b/template/app/src/client/fonts/Satoshi-LightItalic.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-LightItalic.eot rename to template/app/src/client/fonts/Satoshi-LightItalic.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-LightItalic.ttf b/template/app/src/client/fonts/Satoshi-LightItalic.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-LightItalic.ttf rename to template/app/src/client/fonts/Satoshi-LightItalic.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-LightItalic.woff b/template/app/src/client/fonts/Satoshi-LightItalic.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-LightItalic.woff rename to template/app/src/client/fonts/Satoshi-LightItalic.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-LightItalic.woff2 b/template/app/src/client/fonts/Satoshi-LightItalic.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-LightItalic.woff2 rename to template/app/src/client/fonts/Satoshi-LightItalic.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-Medium.eot b/template/app/src/client/fonts/Satoshi-Medium.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Medium.eot rename to template/app/src/client/fonts/Satoshi-Medium.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-Medium.ttf b/template/app/src/client/fonts/Satoshi-Medium.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Medium.ttf rename to template/app/src/client/fonts/Satoshi-Medium.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-Medium.woff b/template/app/src/client/fonts/Satoshi-Medium.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Medium.woff rename to template/app/src/client/fonts/Satoshi-Medium.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-Medium.woff2 b/template/app/src/client/fonts/Satoshi-Medium.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Medium.woff2 rename to template/app/src/client/fonts/Satoshi-Medium.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-MediumItalic.eot b/template/app/src/client/fonts/Satoshi-MediumItalic.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-MediumItalic.eot rename to template/app/src/client/fonts/Satoshi-MediumItalic.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-MediumItalic.ttf b/template/app/src/client/fonts/Satoshi-MediumItalic.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-MediumItalic.ttf rename to template/app/src/client/fonts/Satoshi-MediumItalic.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-MediumItalic.woff b/template/app/src/client/fonts/Satoshi-MediumItalic.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-MediumItalic.woff rename to template/app/src/client/fonts/Satoshi-MediumItalic.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-MediumItalic.woff2 b/template/app/src/client/fonts/Satoshi-MediumItalic.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-MediumItalic.woff2 rename to template/app/src/client/fonts/Satoshi-MediumItalic.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-Regular.eot b/template/app/src/client/fonts/Satoshi-Regular.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Regular.eot rename to template/app/src/client/fonts/Satoshi-Regular.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-Regular.ttf b/template/app/src/client/fonts/Satoshi-Regular.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Regular.ttf rename to template/app/src/client/fonts/Satoshi-Regular.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-Regular.woff b/template/app/src/client/fonts/Satoshi-Regular.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Regular.woff rename to template/app/src/client/fonts/Satoshi-Regular.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-Regular.woff2 b/template/app/src/client/fonts/Satoshi-Regular.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Regular.woff2 rename to template/app/src/client/fonts/Satoshi-Regular.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-Variable.eot b/template/app/src/client/fonts/Satoshi-Variable.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Variable.eot rename to template/app/src/client/fonts/Satoshi-Variable.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-Variable.ttf b/template/app/src/client/fonts/Satoshi-Variable.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Variable.ttf rename to template/app/src/client/fonts/Satoshi-Variable.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-Variable.woff b/template/app/src/client/fonts/Satoshi-Variable.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Variable.woff rename to template/app/src/client/fonts/Satoshi-Variable.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-Variable.woff2 b/template/app/src/client/fonts/Satoshi-Variable.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-Variable.woff2 rename to template/app/src/client/fonts/Satoshi-Variable.woff2 diff --git a/template/app/src/client/admin/fonts/Satoshi-VariableItalic.eot b/template/app/src/client/fonts/Satoshi-VariableItalic.eot similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-VariableItalic.eot rename to template/app/src/client/fonts/Satoshi-VariableItalic.eot diff --git a/template/app/src/client/admin/fonts/Satoshi-VariableItalic.ttf b/template/app/src/client/fonts/Satoshi-VariableItalic.ttf similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-VariableItalic.ttf rename to template/app/src/client/fonts/Satoshi-VariableItalic.ttf diff --git a/template/app/src/client/admin/fonts/Satoshi-VariableItalic.woff b/template/app/src/client/fonts/Satoshi-VariableItalic.woff similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-VariableItalic.woff rename to template/app/src/client/fonts/Satoshi-VariableItalic.woff diff --git a/template/app/src/client/admin/fonts/Satoshi-VariableItalic.woff2 b/template/app/src/client/fonts/Satoshi-VariableItalic.woff2 similarity index 100% rename from template/app/src/client/admin/fonts/Satoshi-VariableItalic.woff2 rename to template/app/src/client/fonts/Satoshi-VariableItalic.woff2 diff --git a/template/app/src/client/admin/images/icon/icon-arrow-down.svg b/template/app/src/client/icons/icon-arrow-down.svg similarity index 100% rename from template/app/src/client/admin/images/icon/icon-arrow-down.svg rename to template/app/src/client/icons/icon-arrow-down.svg diff --git a/template/app/src/client/admin/images/icon/icon-calendar.svg b/template/app/src/client/icons/icon-calendar.svg similarity index 100% rename from template/app/src/client/admin/images/icon/icon-calendar.svg rename to template/app/src/client/icons/icon-calendar.svg diff --git a/template/app/src/client/admin/images/icon/icon-copy-alt.svg b/template/app/src/client/icons/icon-copy-alt.svg similarity index 100% rename from template/app/src/client/admin/images/icon/icon-copy-alt.svg rename to template/app/src/client/icons/icon-copy-alt.svg diff --git a/template/app/src/client/admin/images/icon/icon-moon.svg b/template/app/src/client/icons/icon-moon.svg similarity index 100% rename from template/app/src/client/admin/images/icon/icon-moon.svg rename to template/app/src/client/icons/icon-moon.svg diff --git a/template/app/src/client/admin/images/icon/icon-sun.svg b/template/app/src/client/icons/icon-sun.svg similarity index 100% rename from template/app/src/client/admin/images/icon/icon-sun.svg rename to template/app/src/client/icons/icon-sun.svg diff --git a/template/app/src/client/admin/images/icon/icons-arrows.tsx b/template/app/src/client/icons/icons-arrows.tsx similarity index 100% rename from template/app/src/client/admin/images/icon/icons-arrows.tsx rename to template/app/src/client/icons/icons-arrows.tsx diff --git a/template/app/src/client/landing-page/LandingPage.tsx b/template/app/src/client/landing-page/LandingPage.tsx index 86fe121..d8627ed 100644 --- a/template/app/src/client/landing-page/LandingPage.tsx +++ b/template/app/src/client/landing-page/LandingPage.tsx @@ -11,7 +11,7 @@ import { features, navigation, faqs, footerNavigation, testimonials } from './co import DropdownUser from '../../user/DropdownUser'; import { UserMenuItems } from '../../user/UserMenuItems'; import { DocsUrl } from '../../common'; -import DarkModeSwitcher from '../admin/components/DarkModeSwitcher'; +import DarkModeSwitcher from '../components/DarkModeSwitcher'; export default function LandingPage() { const [mobileMenuOpen, setMobileMenuOpen] = useState(false); diff --git a/template/app/src/client/admin/components/MessageButton.tsx b/template/app/src/messages/MessageButton.tsx similarity index 100% rename from template/app/src/client/admin/components/MessageButton.tsx rename to template/app/src/messages/MessageButton.tsx diff --git a/template/app/src/client/admin/pages/Messages.tsx b/template/app/src/messages/MessagesPage.tsx similarity index 100% rename from template/app/src/client/admin/pages/Messages.tsx rename to template/app/src/messages/MessagesPage.tsx diff --git a/template/app/src/server/queries.ts b/template/app/src/server/queries.ts index 035e7fc..316fe69 100644 --- a/template/app/src/server/queries.ts +++ b/template/app/src/server/queries.ts @@ -1,19 +1,6 @@ -import { type DailyStats, type GptResponse, type User, type PageViewSource, type Task } from 'wasp/entities'; +import { type GptResponse, type Task } from 'wasp/entities'; import { HttpError } from 'wasp/server'; -import { - type GetGptResponses, - type GetDailyStats, - type GetAllTasksByUser, -} from 'wasp/server/operations'; - -type DailyStatsWithSources = DailyStats & { - sources: PageViewSource[]; -}; - -type DailyStatsValues = { - dailyStats: DailyStatsWithSources; - weeklyStats: DailyStatsWithSources[]; -}; +import { type GetGptResponses, type GetAllTasksByUser } from 'wasp/server/operations'; export const getGptResponses: GetGptResponses = async (args, context) => { if (!context.user) { @@ -43,29 +30,3 @@ export const getAllTasksByUser: GetAllTasksByUser = async (_args, }, }); }; - -export const getDailyStats: GetDailyStats = async (_args, context) => { - if (!context.user?.isAdmin) { - throw new HttpError(401); - } - const dailyStats = await context.entities.DailyStats.findFirstOrThrow({ - orderBy: { - date: 'desc', - }, - include: { - sources: true, - }, - }); - - const weeklyStats = await context.entities.DailyStats.findMany({ - orderBy: { - date: 'desc', - }, - take: 7, - include: { - sources: true, - }, - }); - - return { dailyStats, weeklyStats }; -};