From 6d29cc71895ef37c74dde3934be78cbeb0cfac10 Mon Sep 17 00:00:00 2001 From: cyri113 Date: Fri, 11 Apr 2025 16:20:00 +0200 Subject: [PATCH 01/56] datasources --- .../home/datasources/BaseButton.tsx | 5 + .../home/datasources/DatasourceItem.tsx | 39 +++++ .../home/datasources/DatasourceList.tsx | 25 +++ src/components/home/datasources/Spinner.tsx | 5 + .../home/datasources/UpvoteButton.tsx | 48 ++++++ src/pages/centric/welcome.tsx | 151 +----------------- 6 files changed, 129 insertions(+), 144 deletions(-) create mode 100644 src/components/home/datasources/BaseButton.tsx create mode 100644 src/components/home/datasources/DatasourceItem.tsx create mode 100644 src/components/home/datasources/DatasourceList.tsx create mode 100644 src/components/home/datasources/Spinner.tsx create mode 100644 src/components/home/datasources/UpvoteButton.tsx diff --git a/src/components/home/datasources/BaseButton.tsx b/src/components/home/datasources/BaseButton.tsx new file mode 100644 index 00000000..eecc658b --- /dev/null +++ b/src/components/home/datasources/BaseButton.tsx @@ -0,0 +1,5 @@ +export default function BaseButton({ children, onClick }: { children: React.ReactNode, onClick: () => void }) { + return ( + + ); +} \ No newline at end of file diff --git a/src/components/home/datasources/DatasourceItem.tsx b/src/components/home/datasources/DatasourceItem.tsx new file mode 100644 index 00000000..11bff2b0 --- /dev/null +++ b/src/components/home/datasources/DatasourceItem.tsx @@ -0,0 +1,39 @@ +import TcCommunityPlatformIcon from "@/components/communitySettings/communityPlatforms/TcCommunityPlatformIcon"; + +import { UpvoteButton } from "./UpvoteButton"; + +function ConnectButton({ datasource }: { datasource: any }) { + return ( + Connect + ) +} + +function ManageButton({ datasource }: { datasource: any }) { + return ( + Manage + ) +} + + +export default function DatasourceItem({ datasource, connected, community }: { datasource: any, connected: boolean, community: any }) { + + return ( +
  • +
    + +

    {datasource.title}

    +
    +
    + {datasource.isComingSoon ? ( + + ) : ( + connected ? ( + + ) : ( + + ) + )} +
    +
  • + ); +} diff --git a/src/components/home/datasources/DatasourceList.tsx b/src/components/home/datasources/DatasourceList.tsx new file mode 100644 index 00000000..b50dfb42 --- /dev/null +++ b/src/components/home/datasources/DatasourceList.tsx @@ -0,0 +1,25 @@ +import { useToken } from "@/context/TokenContext"; + +import DatasourceItem from "./DatasourceItem"; + +export default function DatasourceList({ datasources }: { datasources: any[] }) { + + const { community } = useToken(); + + const platformNames = + community?.platforms?.map((platform: any) => platform.name) || []; + + const isConnected = (name: string) => platformNames.includes(name.toLowerCase()); + + return ( +
    +
    +
    Data sources
    +
    + + {/*
    */} +
    + ); +} \ No newline at end of file diff --git a/src/components/home/datasources/Spinner.tsx b/src/components/home/datasources/Spinner.tsx new file mode 100644 index 00000000..3ea59de6 --- /dev/null +++ b/src/components/home/datasources/Spinner.tsx @@ -0,0 +1,5 @@ +export function Spinner({ size = 4 }: { size?: number }) { + return ( + + ) +} diff --git a/src/components/home/datasources/UpvoteButton.tsx b/src/components/home/datasources/UpvoteButton.tsx new file mode 100644 index 00000000..476a5e07 --- /dev/null +++ b/src/components/home/datasources/UpvoteButton.tsx @@ -0,0 +1,48 @@ +import { useState } from "react"; + +import Loading from "@/components/global/Loading"; + +import { useSnackbar } from "@/context/SnackbarContext"; +import { setAmplitudeUserIdFromToken, trackAmplitudeEvent } from "@/helpers/amplitudeHelper"; + +import BaseButton from "./BaseButton"; +import { Spinner } from "./Spinner"; + +export function UpvoteButton({ community, datasource }: { community: any, datasource: any }) { + const [loading, setLoading] = useState(false); + const { showMessage } = useSnackbar(); + + const handleClick = () => { + setLoading(true); + try { + setAmplitudeUserIdFromToken(); + + trackAmplitudeEvent({ + eventType: "Upvote Data Source", + eventProperties: { + communityId: community?.id, + communityName: community?.name, + platform: datasource, + }, + callback: () => { + showMessage( + `Thank you for upvoting ${datasource}! We will consider adding it soon.`, + "success", + ); + setLoading(false); + } + }); + } catch (e) { + console.error(e); + setLoading(false); + } + }; + + return ( + +
    + {loading ? : "Upvote"} +
    +
    + ); +} \ No newline at end of file diff --git a/src/pages/centric/welcome.tsx b/src/pages/centric/welcome.tsx index f64fc5ad..57a90890 100644 --- a/src/pages/centric/welcome.tsx +++ b/src/pages/centric/welcome.tsx @@ -21,6 +21,7 @@ import { IoStatsChart } from "react-icons/io5"; import TcCommunityPlatformIcon from "@/components/communitySettings/communityPlatforms/TcCommunityPlatformIcon"; import SEO from "@/components/global/SEO"; +import DatasourceList from "@/components/home/datasources/DatasourceList"; import useAppStore from "@/store/useStore"; @@ -137,40 +138,6 @@ function Welcome() { } }; - const handleConnectPlatform = (dataSource: IDataSources) => () => { - router.push( - `/community-settings/?managePlatform=${dataSource.title.toLocaleLowerCase()}`, - ); - - setAmplitudeUserIdFromToken(); - - trackAmplitudeEvent({ - eventType: "Connect Data Source", - eventProperties: { - communityId: community?.id, - communityName: community?.name, - platform: dataSource.title, - }, - }); - }; - - const handleManagePlatform = (dataSource: IDataSources) => () => { - router.push( - `/community-settings/?addPlatform=${dataSource.title.toLocaleLowerCase()}`, - ); - - setAmplitudeUserIdFromToken(); - - trackAmplitudeEvent({ - eventType: "Manage Data Source", - eventProperties: { - communityId: community?.id, - communityName: community?.name, - platform: dataSource.title, - }, - }); - }; - const handleOpenApplication = (application: string) => () => { setAmplitudeUserIdFromToken(); @@ -257,8 +224,8 @@ function Welcome() { }; return ( - <> - +
    + - +

    Welcome to {community?.name} - +

    {!isAdmin && ( { - return { - xs: "none", - md: `1px solid ${theme.palette.grey[300]}`, - }; - }, - }} pr={{ md: 2, }} > - - - - Data Source - - - - {DATA_SOURCES.map((dataSource) => { - const isConnected = platformNames.includes( - dataSource.title.toLowerCase(), - ); - - return ( - - - - - - {dataSource.title === "Google" - ? "GDrive" - : dataSource.title} - {dataSource.isComingSoon && ( - - )} - - - {dataSource.isComingSoon ? ( - - ) : ( - - )} - - - ); - })} - +
    @@ -485,7 +348,7 @@ function Welcome() {
    - +
    ); } From d7e41397a6532827f3ecda1284a1a67af7ff6088 Mon Sep 17 00:00:00 2001 From: cyri113 Date: Fri, 11 Apr 2025 19:18:28 +0200 Subject: [PATCH 02/56] Applications --- src/components/home/BaseButton.tsx | 5 + .../home/applications/ApplicationItem.tsx | 67 ++++ .../home/applications/ApplicationList.tsx | 26 ++ src/components/home/applications/Toggle.tsx | 14 + .../home/datasources/BaseButton.tsx | 5 - .../home/datasources/DatasourceItem.tsx | 48 ++- .../home/datasources/DatasourceList.tsx | 15 +- .../home/datasources/UpvoteButton.tsx | 10 +- src/hooks/useAdmin.ts | 11 + src/hooks/useApi.ts | 3 +- src/hooks/useApplications.ts | 90 +++++ src/hooks/useDatasources.ts | 37 +++ src/pages/centric/welcome.tsx | 311 +----------------- src/styles/toggle.css | 217 ++++++++++++ 14 files changed, 527 insertions(+), 332 deletions(-) create mode 100644 src/components/home/BaseButton.tsx create mode 100644 src/components/home/applications/ApplicationItem.tsx create mode 100644 src/components/home/applications/ApplicationList.tsx create mode 100644 src/components/home/applications/Toggle.tsx delete mode 100644 src/components/home/datasources/BaseButton.tsx create mode 100644 src/hooks/useAdmin.ts create mode 100644 src/hooks/useApplications.ts create mode 100644 src/hooks/useDatasources.ts create mode 100644 src/styles/toggle.css diff --git a/src/components/home/BaseButton.tsx b/src/components/home/BaseButton.tsx new file mode 100644 index 00000000..e6f58226 --- /dev/null +++ b/src/components/home/BaseButton.tsx @@ -0,0 +1,5 @@ +export default function BaseButton({ children, onClick, disabled }: { children: React.ReactNode, onClick: () => void, disabled: boolean }) { + return ( + + ); +} \ No newline at end of file diff --git a/src/components/home/applications/ApplicationItem.tsx b/src/components/home/applications/ApplicationItem.tsx new file mode 100644 index 00000000..b09cea2e --- /dev/null +++ b/src/components/home/applications/ApplicationItem.tsx @@ -0,0 +1,67 @@ + +import { useToken } from "@/context/TokenContext"; + +import { UpvoteButton } from "../datasources/UpvoteButton"; +import { Toggle } from "./Toggle"; +import { FaCog } from "react-icons/fa"; +import { axiosInstance } from "@/axiosInstance"; +import { useAdmin } from "@/hooks/useAdmin"; + +export default function ApplicationItem({ application }: { application: any }) { + + const { community } = useToken(); + + const { isAdmin } = useAdmin(); + + const handleToggle = async (checked: boolean, id?: string) => { + + if (!id) { + // create + // post to /modules with body { name: application.name, activated: checked } + await axiosInstance.post(`/modules`, { + name: application.name, + activated: checked + }) + } else { + // patch + // patch to /modules/:id with body { activated: checked } + await axiosInstance.patch(`/modules/${id}`, { + activated: checked + }) + } + + } + + return ( +
  • +
    + +

    {application.title}

    +
    +
    + {!application.available ? ( + + ) : ( + <> + + {isAdmin && ( + + + + )} + + // application.active ? ( + // + // ) : ( + // + // ) + )} +
    +
  • + ); +} diff --git a/src/components/home/applications/ApplicationList.tsx b/src/components/home/applications/ApplicationList.tsx new file mode 100644 index 00000000..9ace5b13 --- /dev/null +++ b/src/components/home/applications/ApplicationList.tsx @@ -0,0 +1,26 @@ +import { useEffect } from "react"; + +import { useApplications } from "@/hooks/useApplications"; + +import ApplicationItem from "./ApplicationItem"; + +export default function ApplicationList() { + + const { applications } = useApplications(); + + useEffect(() => { + console.log(applications); + }, [applications]); + + return ( +
    +
    +
    Applications
    +
    +
      + {applications.map((application, index) => )} +
    + {/*
    */} +
    + ); +} \ No newline at end of file diff --git a/src/components/home/applications/Toggle.tsx b/src/components/home/applications/Toggle.tsx new file mode 100644 index 00000000..7314a5cd --- /dev/null +++ b/src/components/home/applications/Toggle.tsx @@ -0,0 +1,14 @@ +export function Toggle({ checked, onChange, id, disabled }: { checked: boolean, onChange: (checked: boolean, id: string) => void, id: string, disabled: boolean }) { + return ( + + ); +} \ No newline at end of file diff --git a/src/components/home/datasources/BaseButton.tsx b/src/components/home/datasources/BaseButton.tsx deleted file mode 100644 index eecc658b..00000000 --- a/src/components/home/datasources/BaseButton.tsx +++ /dev/null @@ -1,5 +0,0 @@ -export default function BaseButton({ children, onClick }: { children: React.ReactNode, onClick: () => void }) { - return ( - - ); -} \ No newline at end of file diff --git a/src/components/home/datasources/DatasourceItem.tsx b/src/components/home/datasources/DatasourceItem.tsx index 11bff2b0..cd441668 100644 --- a/src/components/home/datasources/DatasourceItem.tsx +++ b/src/components/home/datasources/DatasourceItem.tsx @@ -1,37 +1,61 @@ import TcCommunityPlatformIcon from "@/components/communitySettings/communityPlatforms/TcCommunityPlatformIcon"; +import { useToken } from "@/context/TokenContext"; + import { UpvoteButton } from "./UpvoteButton"; +import { useAdmin } from "@/hooks/useAdmin"; +import { FaCog } from "react-icons/fa"; function ConnectButton({ datasource }: { datasource: any }) { return ( - Connect + + + ) } function ManageButton({ datasource }: { datasource: any }) { return ( - Manage + + + ) } -export default function DatasourceItem({ datasource, connected, community }: { datasource: any, connected: boolean, community: any }) { +export default function DatasourceItem({ datasource }: { datasource: any }) { + + const { community } = useToken(); + + const { isAdmin } = useAdmin(); return ( -
  • +
  • - +

    {datasource.title}

    - {datasource.isComingSoon ? ( - + {!datasource.available ? ( + ) : ( - connected ? ( - - ) : ( - - ) + <> +
    + {datasource.activated ? ( +
    + ) : ( +
    + )} + {isAdmin && ( + datasource.activated ? ( + + ) : ( + + ) + )} + +
    + )}
  • diff --git a/src/components/home/datasources/DatasourceList.tsx b/src/components/home/datasources/DatasourceList.tsx index b50dfb42..73df31b9 100644 --- a/src/components/home/datasources/DatasourceList.tsx +++ b/src/components/home/datasources/DatasourceList.tsx @@ -1,23 +1,18 @@ -import { useToken } from "@/context/TokenContext"; +import { useDatasources } from "@/hooks/useDatasources"; import DatasourceItem from "./DatasourceItem"; -export default function DatasourceList({ datasources }: { datasources: any[] }) { +export default function DatasourceList() { - const { community } = useToken(); - - const platformNames = - community?.platforms?.map((platform: any) => platform.name) || []; - - const isConnected = (name: string) => platformNames.includes(name.toLowerCase()); + const datasources = useDatasources(); return (
    Data sources
    -
      - {datasources.map((datasource, index) => )} +
        + {datasources.map((datasource, index) => )}
      {/*
      */}
      diff --git a/src/components/home/datasources/UpvoteButton.tsx b/src/components/home/datasources/UpvoteButton.tsx index 476a5e07..4f59e39d 100644 --- a/src/components/home/datasources/UpvoteButton.tsx +++ b/src/components/home/datasources/UpvoteButton.tsx @@ -5,10 +5,10 @@ import Loading from "@/components/global/Loading"; import { useSnackbar } from "@/context/SnackbarContext"; import { setAmplitudeUserIdFromToken, trackAmplitudeEvent } from "@/helpers/amplitudeHelper"; -import BaseButton from "./BaseButton"; import { Spinner } from "./Spinner"; +import BaseButton from "../BaseButton"; -export function UpvoteButton({ community, datasource }: { community: any, datasource: any }) { +export function UpvoteButton({ community, name }: { community: any, name: string }) { const [loading, setLoading] = useState(false); const { showMessage } = useSnackbar(); @@ -22,12 +22,12 @@ export function UpvoteButton({ community, datasource }: { community: any, dataso eventProperties: { communityId: community?.id, communityName: community?.name, - platform: datasource, + upvote: name, }, callback: () => { showMessage( - `Thank you for upvoting ${datasource}! We will consider adding it soon.`, - "success", + 'Thank you for voting!', + 'success', ); setLoading(false); } diff --git a/src/hooks/useAdmin.ts b/src/hooks/useAdmin.ts new file mode 100644 index 00000000..0b1c9187 --- /dev/null +++ b/src/hooks/useAdmin.ts @@ -0,0 +1,11 @@ +import useAppStore from "@/store/useStore"; + +export const useAdmin = () => { + const userPermissions = useAppStore( + (state) => state.userRolePermissions || [], + ); + + const isAdmin = userPermissions.includes("admin"); + return { isAdmin }; + +}; diff --git a/src/hooks/useApi.ts b/src/hooks/useApi.ts index 4c859b9f..66e53831 100644 --- a/src/hooks/useApi.ts +++ b/src/hooks/useApi.ts @@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from "react"; import { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios"; import { axiosInstance } from "@/axiosInstance"; -export const useApi = (url: string, options: AxiosRequestConfig = {}) => { +export const useApi = (url: string | null, options: AxiosRequestConfig = {}) => { const memoizedOptions = useMemo(() => options, [JSON.stringify(options)]); const [data, setData] = useState(null); const [loading, setLoading] = useState(false); @@ -10,6 +10,7 @@ export const useApi = (url: string, options: AxiosRequestConfig = {}) => { useEffect(() => { const fetchData = async () => { + if (!url) return; setLoading(true); try { const response: AxiosResponse = await axiosInstance.get(url, options); diff --git a/src/hooks/useApplications.ts b/src/hooks/useApplications.ts new file mode 100644 index 00000000..2dd86b86 --- /dev/null +++ b/src/hooks/useApplications.ts @@ -0,0 +1,90 @@ +import { IoCalendar, IoShieldCheckmark, IoTrophy } from "react-icons/io5"; +import { RiRobot2Fill, RiMentalHealthFill, RiTeamFill } from "react-icons/ri"; + +import { useToken } from "@/context/TokenContext"; + +import { useApi } from "./useApi"; + +interface IApplication { + icon: React.ElementType; + id?: string; + name: string; + title: string; + description: string; + available: boolean; + activated?: boolean; + path: string; +} + +const APPLICATIONS: IApplication[] = [ + { + icon: RiTeamFill, + name: "community-insights", + title: "Community Insights", + description: + "Master your community's engagement with detailed insights. Monitor active vs. inactive members, identify new joiners and those disengaging, track participation across user groups, and identify your most valuable contributors.", + available: true, + path: "/community-settings/", + }, + { + icon: RiMentalHealthFill, + name: "community-health", + title: "Community Health", + description: + "Monitor your community's health", + available: true, + path: "/community-settings/", + }, + { + icon: IoCalendar, + name: "announcements", + title: "Announcements", + description: + "Take control of your announcements and communication with members. Send targeted messages to specific types of member based on their roles or engagement levels. Schedule announcements in advance and even reach disengaged members with (safe) DMs.", + available: true, + path: "/announcements", + }, + { + icon: RiRobot2Fill, + name: "hivemind", + title: "AI Assistant", + description: + "24/7 Q&A support for your community. Our AI assistant uses your connected data sources to answer member questions instantly, freeing you to focus on strategic tasks while ensuring consistent, reliable member support.", + available: true, + path: "/community-settings/ai-assistant/", + }, + { + icon: IoTrophy, + name: "dynamicNft", + title: "Reputation", + description: + "Create a culture of genuine participation with our intelligent Reputation Score system. Automatically measure authentic community involvement, while ensuring the system remains fair and resistant to manipulation.", + available: true, + path: "/community-settings/reputation-score/", + }, + { + icon: IoShieldCheckmark, + name: "violationDetection", + title: "Community Guardian", + description: + "Keep your community safe with automatic detection of violent language and community guidelines violations. Our AI ensures credible neutrality, keeping your moderators safe and your standards objective.", + available: true, + path: "/community-settings/violation-detection/", + }, +]; + +export const useApplications = () => { + const { community } = useToken(); + + const { data, loading, error } = useApi( + community?.id ? `/modules?community=${community.id}` : null + ); + + const applications = APPLICATIONS.map((application) => ({ + ...application, + activated: data?.results?.some((module: any) => module.name === application.name && module.activated), + id: data?.results?.find((module: any) => module.name === application.name)?.id, + })); + + return { applications, data, loading, error }; +}; \ No newline at end of file diff --git a/src/hooks/useDatasources.ts b/src/hooks/useDatasources.ts new file mode 100644 index 00000000..233ad780 --- /dev/null +++ b/src/hooks/useDatasources.ts @@ -0,0 +1,37 @@ +import { useToken } from "@/context/TokenContext"; + +interface IDatasource { + name: string; + title: string; + available: boolean; + activated?: boolean; +} + +const DATA_SOURCES: IDatasource[] = [ + { name: "discord", title: "Discord", available: true }, + { name: "telegram", title: "Telegram", available: true }, + { name: "website", title: "Website", available: true }, + { name: "discourse", title: "Discourse", available: true }, + { name: "github", title: "Github", available: true }, + { name: "notion", title: "Notion", available: true }, + { name: "mediawiki", title: "Mediawiki", available: true }, + { name: "x", title: "X (Twitter)", available: false }, + { name: "snapshot", title: "Snapshot", available: false }, + { name: "google", title: "Google", available: false }, + { name: "gitbook", title: "Gitbook", available: false }, +]; + +export const useDatasources = () => { + + const { community } = useToken(); + + const platformNames = + community?.platforms?.map((platform: any) => platform.name) || []; + + const datasources = DATA_SOURCES.map((datasource) => ({ + ...datasource, + activated: platformNames.includes(datasource.name), + })); + + return datasources; +}; diff --git a/src/pages/centric/welcome.tsx b/src/pages/centric/welcome.tsx index 57a90890..c37a1fd4 100644 --- a/src/pages/centric/welcome.tsx +++ b/src/pages/centric/welcome.tsx @@ -1,227 +1,20 @@ import React from "react"; -import { - Alert, - Box, - Button, - Chip, - Grid, - List, - ListItem, - ListItemIcon, - ListItemText, - Paper, - Stack, - Typography, -} from "@mui/material"; -import { useRouter } from "next/navigation"; -import { FaCaretUp } from "react-icons/fa"; -import { FaDatabase, FaStore } from "react-icons/fa"; -import { FaHashtag } from "react-icons/fa6"; -import { IoStatsChart } from "react-icons/io5"; +import { Grid } from "@mui/material"; + -import TcCommunityPlatformIcon from "@/components/communitySettings/communityPlatforms/TcCommunityPlatformIcon"; import SEO from "@/components/global/SEO"; +import ApplicationList from "@/components/home/applications/ApplicationList"; import DatasourceList from "@/components/home/datasources/DatasourceList"; -import useAppStore from "@/store/useStore"; - -import { useSnackbar } from "@/context/SnackbarContext"; import { useToken } from "@/context/TokenContext"; -import { - setAmplitudeUserIdFromToken, - trackAmplitudeEvent, -} from "@/helpers/amplitudeHelper"; import { defaultLayout } from "@/layouts/defaultLayout"; import { withRoles } from "@/utils/withRoles"; - -const DATA_SOURCES = [ - { title: "Discord", isComingSoon: false }, - { title: "Telegram", isComingSoon: false }, - { title: "Website", isComingSoon: false }, - { title: "Discourse", isComingSoon: false }, - { title: "Github", isComingSoon: false }, - { title: "Notion", isComingSoon: false }, - { title: "MediaWiki", isComingSoon: false }, - { title: "X", isComingSoon: true }, - { title: "Snapshot", isComingSoon: true }, - { title: "Google", isComingSoon: true }, - { title: "Gitbook", isComingSoon: true }, -]; - -const APPLICATION_MARKETPLACES = [ - { - icon: , - title: "Analytics", - description: - "Master your community's engagement with detailed insights. Monitor active vs. inactive members, identify new joiners and those disengaging, track participation across user groups, and identify your most valuable contributors.", - isManageable: true, - isOpenable: true, - }, - { - icon: , - title: "Announcements", - description: - "Take control of your announcements and communication with members. Send targeted messages to specific types of member based on their roles or engagement levels. Schedule announcements in advance and even reach disengaged members with (safe) DMs.", - isManageable: false, - isOpenable: true, - }, - { - icon: , - title: "Ai Assistance", - description: - "24/7 Q&A support for your community. Our AI assistant uses your connected data sources to answer member questions instantly, freeing you to focus on strategic tasks while ensuring consistent, reliable member support.", - isManageable: true, - isOpenable: false, - }, - { - icon: , - title: "Reputation", - description: - "Create a culture of genuine participation with our intelligent Reputation Score system. Automatically measure authentic community involvement, while ensuring the system remains fair and resistant to manipulation.", - isManageable: true, - isOpenable: true, - }, - { - icon: , - title: "Community Guardian", - description: - "Keep your community safe with automatic detection of violent language and community guidelines violations. Our AI ensures credible neutrality, keeping your moderators safe and your standards objective.", - isManageable: true, - isOpenable: false, - }, - { - icon: , - title: "Coming Soon", - description: - "Vote on upcoming features and shape our roadmap. Your input directly influences our development priorities, ensuring we build what matters most to you.", - isManageable: false, - isOpenable: false, - }, -]; - -interface IDataSources { - title: string; - isComingSoon: boolean; -} +import { useAdmin } from "@/hooks/useAdmin"; function Welcome() { - const userPermissions = useAppStore( - (state) => state.userRolePermissions || [], - ); - const router = useRouter(); - const { community } = useToken(); - const { showMessage } = useSnackbar(); - - const platformNames = - community?.platforms?.map((platform) => platform.name) || []; - - const isAdmin = userPermissions.includes("admin"); - - const handleUpvote = (dataSource: string) => () => { - try { - setAmplitudeUserIdFromToken(); - trackAmplitudeEvent({ - eventType: "Upvote Data Source", - eventProperties: { - communityId: community?.id, - communityName: community?.name, - platform: dataSource, - }, - }); - showMessage( - `Thank you for upvoting ${dataSource}! We will consider adding it soon.`, - "success", - ); - } catch (e) { - console.error(e); - } - }; - - const handleOpenApplication = (application: string) => () => { - setAmplitudeUserIdFromToken(); - - trackAmplitudeEvent({ - eventType: "Open Application Marketplace", - eventProperties: { - communityId: community?.id, - communityName: community?.name, - platform: application, - }, - }); - - switch (application) { - case "Analytics": - router.push("/"); - break; - case "Announcements": - router.push("/announcements"); - break; - case "Ai Assistance": - router.push("/community-settings/ai-assistant/"); - break; - case "Reputation": - router.push("/reputation-score/"); - break; - case "Community Guardian": - router.push("/community-settings/violation-detection/"); - break; - case "Coming Soon": - showMessage("This application is coming soon!", "info"); - break; - default: - break; - } - }; - - const handleManageApplication = (application: string) => () => { - setAmplitudeUserIdFromToken(); - - trackAmplitudeEvent({ - eventType: "Manage Application Marketplace", - eventProperties: { - communityId: community?.id, - communityName: community?.name, - platform: application, - }, - }); - - switch (application) { - case "Analytics": - router.push("/community-settings/"); - break; - case "Announcements": - router.push("/announcements"); - break; - case "Ai Assistance": - router.push("/community-settings/ai-assistant/"); - break; - case "Reputation": - router.push("/community-settings/reputation-score/"); - break; - case "Community Guardian": - router.push("/community-settings/violation-detection/"); - break; - case "Coming Soon": - showMessage("This application is coming soon!", "info"); - break; - default: - break; - } - }; - - const handleOpenForum = () => { - setAmplitudeUserIdFromToken(); - - trackAmplitudeEvent({ - eventType: "Coming Soon Forum", - eventProperties: { - communityId: community?.id, - communityName: community?.name, - }, - }); - window.open("https://tally.so/r/m6WNE5", "_blank"); - }; + const { community } = useToken(); + const { isAdmin } = useAdmin(); return (
      @@ -244,13 +37,11 @@ function Welcome() { Welcome to {community?.name} {!isAdmin && ( - - Add/Manage community Data-sources/Applications needs - admin permissions. please contact your admin to get access. - + Only administrators can manage datasources and applications. +
      )} @@ -262,89 +53,11 @@ function Welcome() { md: 2, }} > - + - - - - Application Marketplace - - - - - {APPLICATION_MARKETPLACES.map((application) => ( - - -
      - - {application.icon} - - {application.title} - - - - {application.description} - -
      -
      - - {application.isOpenable && ( - - )} - {application.isManageable && ( - - )} - - {!application.isOpenable && !application.isManageable && ( - - )} -
      -
      -
      - ))} -
      +
      diff --git a/src/styles/toggle.css b/src/styles/toggle.css new file mode 100644 index 00000000..8893de5a --- /dev/null +++ b/src/styles/toggle.css @@ -0,0 +1,217 @@ +.toggle { + border: var(--border) solid currentColor; + color: var(--input-color); + @apply relative inline-grid shrink-0 cursor-pointer select-none appearance-none place-content-center align-middle; + grid-template-columns: 0fr 1fr 1fr; + /* --radius-selector-max is a separate variable because ~ calc(min(calc(--var))) ~ gives build error in PostCSS+Nuxt */ + --radius-selector-max: calc( + var(--radius-selector) + var(--radius-selector) + var(--radius-selector) + ); + border-radius: calc( + var(--radius-selector) + min(var(--toggle-p), var(--radius-selector-max)) + + min(var(--border), var(--radius-selector-max)) + ); + + padding: var(--toggle-p); + box-shadow: 0 1px + color-mix(in oklab, currentColor calc(var(--depth) * 10%), #0000) inset; + transition: + color 0.3s, + grid-template-columns 0.2s; + --input-color: color-mix(in oklab, var(--color-base-content) 50%, #0000); + --toggle-p: 0.1875rem; + --size: calc(var(--size-selector, 0.25rem) * 6); + width: calc((var(--size) * 2) - (var(--border) + var(--toggle-p)) * 2); + height: var(--size); + + /* icons in toggle */ + > * { + @apply z-1 col-span-1 col-start-2 row-start-1 h-full cursor-pointer appearance-none bg-transparent p-0.5; + transition: + opacity 0.2s, + rotate 0.4s; + border: none; + &:focus { + @apply outline-hidden; + } + &:nth-child(2) { + @apply text-base-100; + rotate: 0deg; + } + &:nth-child(3) { + @apply text-base-100 opacity-0; + rotate: -15deg; + } + } + &:has(:checked) { + > :nth-child(2) { + @apply opacity-0; + rotate: 15deg; + } + > :nth-child(3) { + @apply opacity-100; + rotate: 0deg; + } + } + &:before { + @apply rounded-selector relative start-0 col-start-2 row-start-1 aspect-square h-full bg-current; + translate: 0; + --tw-content: ''; + content: var(--tw-content); + transition: + background-color 0.1s, + translate 0.2s, + inset-inline-start 0.2s; + box-shadow: + 0 -1px oklch(0% 0 0 / calc(var(--depth) * 0.1)) inset, + 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * 0.1)) inset, + 0 1px color-mix(in oklab, currentColor calc(var(--depth) * 10%), #0000); + background-size: auto, calc(var(--noise) * 100%); + background-image: none, var(--fx-noise); + } + @media (forced-colors: active) { + &:before { + @apply outline -outline-offset-1; + } + } + @media print { + &:before { + outline: 0.25rem solid; + outline-offset: -1rem; + } + } + + &:focus-visible, + &:has(:focus-visible) { + outline: 2px solid currentColor; + outline-offset: 2px; + } + + &:checked, + &[aria-checked='true'], + &:has(> input:checked) { + grid-template-columns: 1fr 1fr 0fr; + @apply bg-base-100; + --input-color: var(--color-base-content); + + &:before { + @apply bg-current; + } + @starting-style { + &:before { + opacity: 0; + } + } + } + + &:indeterminate { + grid-template-columns: 0.5fr 1fr 0.5fr; + } + + &:disabled { + @apply cursor-not-allowed opacity-30; + + &:before { + @apply bg-transparent; + border: var(--border) solid currentColor; + } + } +} + +.toggle-primary { + &:checked, + &[aria-checked='true'] { + --input-color: var(--color-primary); + } +} + +.toggle-secondary { + &:checked, + &[aria-checked='true'] { + --input-color: var(--color-secondary); + } +} + +.toggle-accent { + &:checked, + &[aria-checked='true'] { + --input-color: var(--color-accent); + } +} + +.toggle-neutral { + &:checked, + &[aria-checked='true'] { + --input-color: var(--color-neutral); + } +} + +.toggle-success { + &:checked, + &[aria-checked='true'] { + --input-color: var(--color-success); + } +} + +.toggle-warning { + &:checked, + &[aria-checked='true'] { + --input-color: var(--color-warning); + } +} + +.toggle-info { + &:checked, + &[aria-checked='true'] { + --input-color: var(--color-info); + } +} + +.toggle-error { + &:checked, + &[aria-checked='true'] { + --input-color: var(--color-error); + } +} + +/* responsive */ + +.toggle-xs { + &:is([type='checkbox']), + &:has([type='checkbox']) { + --toggle-p: 0.0625rem; + --size: calc(var(--size-selector, 0.25rem) * 4); + } +} + +.toggle-sm { + &:is([type='checkbox']), + &:has([type='checkbox']) { + --toggle-p: 0.125rem; + --size: calc(var(--size-selector, 0.25rem) * 5); + } +} + +.toggle-md { + &:is([type='checkbox']), + &:has([type='checkbox']) { + --toggle-p: 0.1875rem; + --size: calc(var(--size-selector, 0.25rem) * 6); + } +} + +.toggle-lg { + &:is([type='checkbox']), + &:has([type='checkbox']) { + --toggle-p: 0.25rem; + --size: calc(var(--size-selector, 0.25rem) * 7); + } +} + +.toggle-xl { + &:is([type='checkbox']), + &:has([type='checkbox']) { + --toggle-p: 0.3125rem; + --size: calc(var(--size-selector, 0.25rem) * 8); + } +} From e0ed5d8c24c474aad87e04693ac2f81513382f3e Mon Sep 17 00:00:00 2001 From: cyri113 Date: Fri, 11 Apr 2025 19:47:42 +0200 Subject: [PATCH 03/56] home layout --- src/components/layouts/Sidebar.tsx | 2 +- src/layouts/defaultLayout.tsx | 2 +- src/pages/centric/welcome.tsx | 74 +++++++++++++----------------- 3 files changed, 33 insertions(+), 45 deletions(-) diff --git a/src/components/layouts/Sidebar.tsx b/src/components/layouts/Sidebar.tsx index 528b7a4e..8782e1c2 100644 --- a/src/components/layouts/Sidebar.tsx +++ b/src/components/layouts/Sidebar.tsx @@ -141,7 +141,7 @@ const Sidebar = () => { ); return ( -