aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Nanis2025-06-24 19:04:01 +0700
committerMax Nanis2025-06-24 19:04:01 +0700
commit80539188ef6814b4202d677d62b761bd5b670574 (patch)
treebf922d15d2cc634c958b14abb4bdb6893bf9154a /src
parent8138549f64403874eb7c7ddfbde1cc2cc2c03695 (diff)
downloadpanel-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.tsx52
-rw-r--r--src/components/app-sidebar.tsx82
-rw-r--r--src/components/nav-main.tsx94
-rw-r--r--src/components/site-header.tsx9
-rw-r--r--src/index.css19
-rw-r--r--src/main.tsx8
-rw-r--r--src/pages/Demographics.tsx2
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"/>