diff options
| author | Max Nanis | 2025-06-24 19:04:01 +0700 |
|---|---|---|
| committer | Max Nanis | 2025-06-24 19:04:01 +0700 |
| commit | 80539188ef6814b4202d677d62b761bd5b670574 (patch) | |
| tree | bf922d15d2cc634c958b14abb4bdb6893bf9154a /src | |
| parent | 8138549f64403874eb7c7ddfbde1cc2cc2c03695 (diff) | |
| download | panel-ui-80539188ef6814b4202d677d62b761bd5b670574.tar.gz panel-ui-80539188ef6814b4202d677d62b761bd5b670574.zip | |
Dynamic height adjustment for widget size. CSS inject by JS for single file
Diffstat (limited to 'src')
| -rw-r--r-- | src/Widget.tsx | 52 | ||||
| -rw-r--r-- | src/components/app-sidebar.tsx | 82 | ||||
| -rw-r--r-- | src/components/nav-main.tsx | 94 | ||||
| -rw-r--r-- | src/components/site-header.tsx | 9 | ||||
| -rw-r--r-- | src/index.css | 19 | ||||
| -rw-r--r-- | src/main.tsx | 8 | ||||
| -rw-r--r-- | src/pages/Demographics.tsx | 2 |
7 files changed, 131 insertions, 135 deletions
diff --git a/src/Widget.tsx b/src/Widget.tsx index 192e4e0..4f4556b 100644 --- a/src/Widget.tsx +++ b/src/Widget.tsx @@ -1,5 +1,5 @@ -import {useEffect} from 'react' -import {AppSidebar} from "@/components/app-sidebar" +import { useEffect, useState, useRef } from "react" + import {SiteHeader} from "@/components/site-header" import {SidebarInset, SidebarProvider} from "@/components/ui/sidebar" import {Offerwall} from "@/pages/Offerwall.tsx" @@ -8,6 +8,7 @@ import {Demographics} from "@/pages/Demographics.tsx" import {CashoutMethodsPage} from "@/pages/CashoutMethods.tsx"; import {TransactionHistoryPage} from "@/pages/TransactionHistory.tsx" import {TaskAttemptHistoryPage} from "@/pages/TaskAttemptHistory.tsx"; +import {AppSidebar} from "@/components/app-sidebar" import {useAppDispatch, useAppSelector} from "@/hooks.ts"; import { @@ -33,11 +34,34 @@ import {setMarketplaceAnswers} from "@/models/userMarketplaceAnswerSlice.ts"; import {setUserProfile} from "@/models/userProfileSlice.ts"; import {setTaskStatuses} from "@/models/taskStatusSlice.ts" import {App} from "@/models/app.ts" +import {ScrollArea} from "@/components/ui/scroll-area" import './index.css'; +export function useParentHeight() { + const ref = useRef<HTMLDivElement>(null) + const [height, setHeight] = useState<number | null>(null) + + useEffect(() => { + if (!ref.current) return + + const observer = new ResizeObserver(() => { + if (ref.current?.parentElement) { + const h = ref.current.parentElement.getBoundingClientRect().height + setHeight(h) + } + }) + + observer.observe(ref.current.parentElement!) + + return () => observer.disconnect() + }, []) + + return { ref, height } +} const Widget = () => { + const { ref, height } = useParentHeight() const dispatch = useAppDispatch() const app: App = useAppSelector(state => state.app) @@ -103,31 +127,29 @@ const Widget = () => { }, []); // ← empty array means "run once" - return ( - <SidebarProvider> - <AppSidebar variant="floating"/> - <SidebarInset> - <SiteHeader/> + <div ref={ref} className="w-full h-full bg-white rounded-lg shadow relative"> + <SidebarProvider className="bg-blend-darken h-full flex flex-1" style={{ height }}> + <AppSidebar className="h-full" style={{ height }}/> - <div className="flex flex-1 flex-col"> - <div className="@container/main flex flex-1 flex-col gap-2"> + <SidebarInset className="h-full" style={{ height }}> + <SiteHeader/> + <ScrollArea className="overflow-auto px-4" style={{ maxHeight: height ? height - 24 : undefined }}> <div className="flex flex-col gap-4 py-4 md:gap-6 md:py-6"> - <div className="px-4 lg:px-6"> + <div className="px-4 lg:px-6 bg-white"> {app.currentPage === 'offerwall' && <Offerwall/>} {app.currentPage === 'questions' && <QuestionsPage/>} {app.currentPage === 'cashout_methods' && <CashoutMethodsPage/>} {app.currentPage === 'task_attempts' && <TaskAttemptHistoryPage/>} - {app.currentPage === 'demographics' && <Demographics/>} {app.currentPage === 'transaction_history' && <TransactionHistoryPage/>} </div> </div> - </div> - </div> + </ScrollArea> - </SidebarInset> - </SidebarProvider> + </SidebarInset> + </SidebarProvider> + </div> ) } diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx index c60bf17..b61a716 100644 --- a/src/components/app-sidebar.tsx +++ b/src/components/app-sidebar.tsx @@ -1,9 +1,7 @@ "use client" import React from "react" -import {CircleDollarSign, SquareStack} from "lucide-react" - -import {NavMain} from "@/components/nav-main" +import {Activity, CircleDollarSign, ListIcon, NotebookText, SquareStack, User} from "lucide-react" import { Sidebar, SidebarContent, @@ -22,6 +20,8 @@ import {Badge} from "@/components/ui/badge.tsx"; import {useSelector} from "react-redux"; import {selectCashoutMethods} from "@/models/cashoutMethodSlice.ts"; import {selectTransactionHistory} from "@/models/transactionHistorySlice.ts"; +import {selectQuestions} from "../models/questionSlice"; +import {selectUserUpkAnswers} from "../models/userUpkAnswerSlice"; export function AppSidebar({...props}: React.ComponentProps<typeof Sidebar>) { const app: App = useAppSelector(state => state.app) @@ -29,8 +29,12 @@ export function AppSidebar({...props}: React.ComponentProps<typeof Sidebar>) { const cashoutMethods = useSelector(selectCashoutMethods) const transactionHistory = useSelector(selectTransactionHistory) + const questions = useSelector(selectQuestions) + const upkAnswers = useSelector(selectUserUpkAnswers) + const taskAttempts = useAppSelector(state => state.taskStatus) + return ( - <Sidebar collapsible="offcanvas" {...props}> + <Sidebar collapsible="none" {...props}> <SidebarHeader> <SidebarMenu> <SidebarMenuItem key="panel_name"> @@ -38,7 +42,6 @@ export function AppSidebar({...props}: React.ComponentProps<typeof Sidebar>) { asChild className="data-[slot=sidebar-menu-button]:!p-1.5" > - <span className="text-base font-semibold">{app.panelName}</span> </SidebarMenuButton> </SidebarMenuItem> @@ -46,10 +49,73 @@ export function AppSidebar({...props}: React.ComponentProps<typeof Sidebar>) { </SidebarHeader> <SidebarContent> - <NavMain></NavMain> - </SidebarContent> + <SidebarGroup> + <SidebarGroupContent className="flex flex-col gap-2"> + <SidebarMenu> + + <SidebarMenuItem key="surveys" + onClick={() => dispatch(setPage("offerwall"))} + > + <SidebarMenuButton tooltip="Surveys"> + <NotebookText/> + <span> + Surveys <Badge + className="absolute top-2 right-2 h-5 min-w-5 rounded-full px-1 font-mono tabular-nums cursor-pointer" + variant="outline" + title={`${(app.availability_count ?? 0).toLocaleString()} live surveys`} + >{(app.availability_count ?? 0).toLocaleString()}</Badge> + </span> + </SidebarMenuButton> + </SidebarMenuItem> + + + <SidebarMenuItem key="questions" + onClick={() => dispatch(setPage("questions"))} + > + <SidebarMenuButton tooltip="Questions"> + <ListIcon/> + <span> + Questions <Badge + className="absolute top-2 right-2 h-5 min-w-5 rounded-full px-1 font-mono tabular-nums cursor-pointer" + variant="outline" + title={`${questions.length.toLocaleString()} profiling question available`} + >{questions.length.toLocaleString()}</Badge> + </span> + </SidebarMenuButton> + </SidebarMenuItem> + + <SidebarMenuItem key="demographics" + onClick={() => dispatch(setPage("demographics"))} + > + <SidebarMenuButton tooltip="User Demographics"> + <User/> + <span> + Demographics <Badge + className="absolute top-2 right-2 h-5 min-w-5 rounded-full px-1 font-mono tabular-nums cursor-pointer" + variant="outline" + >{upkAnswers.length.toLocaleString()}</Badge> + </span> + </SidebarMenuButton> + </SidebarMenuItem> + + <SidebarMenuItem key="task_attempts" + onClick={() => dispatch(setPage("task_attempts"))} + > + <SidebarMenuButton tooltip="Survey History"> + <Activity/> + <span> + Survey History <Badge + className="absolute top-2 right-2 h-5 min-w-5 rounded-full px-1 font-mono tabular-nums cursor-pointer" + variant="outline" + >{taskAttempts.length.toLocaleString()}</Badge> + </span> + </SidebarMenuButton> + </SidebarMenuItem> + + </SidebarMenu> + </SidebarGroupContent> + </SidebarGroup> - <SidebarContent> <SidebarGroup> <SidebarGroupLabel>Redemption</SidebarGroupLabel> <SidebarGroupContent> diff --git a/src/components/nav-main.tsx b/src/components/nav-main.tsx deleted file mode 100644 index 9ed1b24..0000000 --- a/src/components/nav-main.tsx +++ /dev/null @@ -1,94 +0,0 @@ -"use client" - -import {ListIcon, NotebookText, Users, User, Activity} from "lucide-react" -import { - SidebarGroup, - SidebarGroupContent, - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, -} from "@/components/ui/sidebar" -import {setPage} from "@/models/appSlice.ts"; -import {useAppDispatch, useAppSelector} from "@/hooks.ts"; -import {useSelector} from "react-redux"; -import {selectQuestions} from "@/models/questionSlice.ts"; -import {Badge} from "@/components/ui/badge" -import {selectUserUpkAnswers} from "@/models/userUpkAnswerSlice.ts"; - -export function NavMain() { - const dispatch = useAppDispatch() - - const app = useAppSelector(state => state.app) - const questions = useSelector(selectQuestions) - const upkAnswers = useSelector(selectUserUpkAnswers) - const taskAttempts = useAppSelector(state => state.taskStatus) - - return ( - <SidebarGroup> - <SidebarGroupContent className="flex flex-col gap-2"> - <SidebarMenu> - - <SidebarMenuItem key="surveys" - onClick={() => dispatch(setPage("offerwall"))} - > - <SidebarMenuButton tooltip="Surveys"> - <NotebookText/> - <span> - Surveys <Badge - className="absolute top-2 right-2 h-5 min-w-5 rounded-full px-1 font-mono tabular-nums cursor-pointer" - variant="outline" - title={`${(app.availability_count ?? 0).toLocaleString()} live surveys`} - >{(app.availability_count ?? 0).toLocaleString()}</Badge> - </span> - </SidebarMenuButton> - </SidebarMenuItem> - - - <SidebarMenuItem key="questions" - onClick={() => dispatch(setPage("questions"))} - > - <SidebarMenuButton tooltip="Questions"> - <ListIcon/> - <span> - Questions <Badge - className="absolute top-2 right-2 h-5 min-w-5 rounded-full px-1 font-mono tabular-nums cursor-pointer" - variant="outline" - title={`${questions.length.toLocaleString()} profiling question available`} - >{questions.length.toLocaleString()}</Badge> - </span> - </SidebarMenuButton> - </SidebarMenuItem> - - <SidebarMenuItem key="demographics" - onClick={() => dispatch(setPage("demographics"))} - > - <SidebarMenuButton tooltip="User Demographics"> - <User/> - <span> - Demographics <Badge - className="absolute top-2 right-2 h-5 min-w-5 rounded-full px-1 font-mono tabular-nums cursor-pointer" - variant="outline" - >{upkAnswers.length.toLocaleString()}</Badge> - </span> - </SidebarMenuButton> - </SidebarMenuItem> - - <SidebarMenuItem key="task_attempts" - onClick={() => dispatch(setPage("task_attempts"))} - > - <SidebarMenuButton tooltip="Survey History"> - <Activity/> - <span> - Survey History <Badge - className="absolute top-2 right-2 h-5 min-w-5 rounded-full px-1 font-mono tabular-nums cursor-pointer" - variant="outline" - >{taskAttempts.length.toLocaleString()}</Badge> - </span> - </SidebarMenuButton> - </SidebarMenuItem> - - </SidebarMenu> - </SidebarGroupContent> - </SidebarGroup> - ) -} diff --git a/src/components/site-header.tsx b/src/components/site-header.tsx index dca4996..70a2068 100644 --- a/src/components/site-header.tsx +++ b/src/components/site-header.tsx @@ -1,8 +1,6 @@ import {Separator} from "@/components/ui/separator" -import {SidebarTrigger} from "@/components/ui/sidebar" import {useAppSelector} from "@/hooks.ts"; import {App} from "@/models/app.ts" -import {Offerwall} from "@/pages/Offerwall.tsx"; const SiteHeader = () => { const app: App = useAppSelector(state => state.app) @@ -10,13 +8,8 @@ const SiteHeader = () => { return ( <header className="group-has-data-[collapsible=icon]/sidebar-wrapper:h-12 flex h-12 shrink-0 items-center gap-2 border-b transition-[width,height] ease-linear"> - <div className="flex w-full items-center gap-1 px-4 lg:gap-2 lg:px-6"> - <SidebarTrigger/> + <div className="flex w-full items-center gap-1 px-2 lg:gap-2 lg:px-4"> - <Separator - orientation="vertical" - className="mx-2 data-[orientation=vertical]:h-4" - /> <h1 className="text-base font-medium"> {app.currentPage === 'offerwall' && "Offerwall"} {app.currentPage === 'questions' && "Profiling Questions"} diff --git a/src/index.css b/src/index.css index e3beb23..39f436b 100644 --- a/src/index.css +++ b/src/index.css @@ -4,11 +4,6 @@ @tailwind components; @tailwind utilities; -#testD4rN { - max-width: 800px; - max-height: 400px !important; -} - @custom-variant dark (&:is(.dark *)); @theme inline { @@ -145,4 +140,16 @@ body { @apply bg-background text-foreground; } -}
\ No newline at end of file +} + +#testD4rN { + /*max-width: 800px;*/ + /*max-height: 400px !important;*/ + + height: 500px; + width: 800px; + border: 1px solid red; + position: absolute; + top: 80px; + left: 80px; +} diff --git a/src/main.tsx b/src/main.tsx index 3dfd07a..c944cdd 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -6,6 +6,8 @@ import {Provider} from 'react-redux' import {store} from './store' import {setApp} from "@/models/appSlice.ts"; +import "@/index.css" + (function () { // Finding the script tag on the page.. @@ -42,9 +44,9 @@ import {setApp} from "@/models/appSlice.ts"; const root = createRoot(container) root.render( // <React.StrictMode> - <Provider store={store}> - <Widget/> - </Provider> + <Provider store={store}> + <Widget/> + </Provider> // </React.StrictMode> ); diff --git a/src/pages/Demographics.tsx b/src/pages/Demographics.tsx index 2031511..f7f6efa 100644 --- a/src/pages/Demographics.tsx +++ b/src/pages/Demographics.tsx @@ -101,7 +101,7 @@ export const ContactCard = () => { <CardContent className="space-y-2 pt-2"> <div className="flex items-center space-x-2 text-sm text-muted-foreground"> <User className="w-4 h-4"/> - <span>{titleCase(gender as string) ?? " - "}</span> + <span>{titleCase(gender ?? " - " as string)}</span> </div> <div className="flex items-center space-x-2 text-sm text-muted-foreground"> <Calendar className="w-4 h-4"/> |
