aboutsummaryrefslogtreecommitdiff
path: root/src/pages/CashoutMethods.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/pages/CashoutMethods.tsx')
-rw-r--r--src/pages/CashoutMethods.tsx207
1 files changed, 182 insertions, 25 deletions
diff --git a/src/pages/CashoutMethods.tsx b/src/pages/CashoutMethods.tsx
index 9656087..fca6af0 100644
--- a/src/pages/CashoutMethods.tsx
+++ b/src/pages/CashoutMethods.tsx
@@ -1,45 +1,202 @@
-import React, {useEffect, useState} from 'react'
+import React, {useState} from 'react'
+import {Card, CardContent, CardHeader,} from "@/components/ui/card"
+import {Tabs, TabsContent, TabsList, TabsTrigger,} from "@/components/ui/tabs"
+import {Badge} from "@/components/ui/badge"
+
+import {selectFixedCashoutMethods, selectVariableCashoutMethods} from "@/models/cashoutMethodSlice.ts";
+import {CashoutMethodOut, UserWalletBalance} from "@/api"
+import {formatCentsToUSD} from "@/lib/utils.ts";
+import {useSelector} from 'react-redux'
+import {motion} from "framer-motion";
+import {Drawer, DrawerContent, DrawerDescription, DrawerHeader, DrawerTitle,} from "@/components/ui/drawer"
+import {useAppSelector} from "@/hooks.ts";
+
+const CashoutAcknowledgement = () => {
+ return (
+ <>
+ <p>Your request has been successfully submitted!</p>
+ <div className="form-group">
+ <label htmlFor="cashout-acknowledgement-transaction-id-input">Transaction ID</label>
+ <input type="email" className="form-control"
+ id="cashout-acknowledgement-transaction-id-input"
+ aria-describedby="transactionIdHelp"
+ readOnly/>
+ <small id="transactionIdHelp" className="form-text">Request Status:
+ <strong>Pending</strong></small>
+ </div>
+ <p>Your redemption link will be on the <a href="/history/">history page</a>.</p>
+ </>
+ )
+}
+
+const CashoutReview: React.FC<{ cashout_method: CashoutMethodOut }> = ({cashout_method}) => {
+ return (
+ <>
+ <p>You are about to redeem <strong id="cashout-review-redeem-amount"></strong> to a card.</p>
+ <img src="<%= image_url %>" alt="..."/>
+ <p>{cashout_method.name}</p>
+ {/*<p>{data.terms}</p>*/}
+ <button id="cashout-review-cancel" type="button"
+ className="btn btn-block">Cancel
+ </button>
+ <button id="cashout-review-submit" type="button"
+ className="btn btn-block">Submit
+ </button>
+ <p id="cashout-review-msg"></p>
+ </>
+ )
+}
+
+const VariableCashoutMethodPreview: React.FC<{ cashout_method: CashoutMethodOut }> = ({cashout_method}) => {
+ return (
+ <>
+ <motion.h1
+ initial={{opacity: 0, scale: 0.8, y: 10}}
+ animate={{opacity: 1, scale: 1, y: 0}}
+ transition={{
+ duration: 0.25,
+ type: "spring",
+ stiffness: 100,
+ damping: 10,
+ }}
+ className="font-bold text-center"
+ >
+ {cashout_method.name}
+ </motion.h1>
+
+ <motion.h2
+ initial={{opacity: 0, scale: 0.8, y: 10}}
+ animate={{opacity: 1, scale: 1, y: 0}}
+ transition={{
+ duration: 0.25,
+ type: "spring",
+ stiffness: 100,
+ damping: 10,
+ }}
+ className="text-center"
+ >
+ {formatCentsToUSD(cashout_method.min_value)} – {formatCentsToUSD(cashout_method.max_value)}
+ </motion.h2>
+ </>
+ )
+}
+
+const FixedCashoutMethodPreview: React.FC<{ cashout_method: CashoutMethodOut }> = ({cashout_method}) => {
+ return (
+ <>
+ <motion.h1
+ initial={{opacity: 0, scale: 0.8, y: 10}}
+ animate={{opacity: 1, scale: 1, y: 0}}
+ transition={{
+ duration: 0.25,
+ type: "spring",
+ stiffness: 100,
+ damping: 10,
+ }}
+ className="font-bold text-center"
+ >
+ {cashout_method.name}
+ </motion.h1>
+ </>
+ )
+}
-import {Card, CardContent, CardHeader} from "@/components/ui/card.tsx";
-import {CashoutMethodOut, CashoutMethodsResponse, WalletApi} from "@/api"
const CashoutMethodPreview: React.FC<{ cashout_method: CashoutMethodOut }> = ({cashout_method}) => {
+ const [open, setOpen] = useState(false)
+
+ const renderContent = () => {
+ switch (cashout_method.data.value_type) {
+ case 'fixed':
+ return <FixedCashoutMethodPreview cashout_method={cashout_method}/>
+ case 'variable':
+ return <VariableCashoutMethodPreview cashout_method={cashout_method}/>
+ }
+ };
+
return (
- <Card key={cashout_method.id}>
+ <Card
+ key={cashout_method.id}
+ className="@container/card relative overflow-hidden h-full min-h-[140px] flex flex-col justify-between cursor-pointer"
+ >
<CardHeader>
- {cashout_method.name}
+ {renderContent()}
</CardHeader>
<CardContent>
- <img className="blur-xs grayscale" src={cashout_method.imageUrl}/>
+ <img
+ className="grayscale blur-[1px] transition-all duration-300 hover:grayscale-0 hover:blur-none"
+ alt="Cashout method"
+ src={cashout_method.image_url}/>
</CardContent>
+
+ <Badge
+ className="absolute bottom-1 right-1 h-5 min-w-5 rounded-full px-1 font-mono tabular-nums cursor-pointer"
+ variant="outline"
+ title="Cashout Details"
+ onClick={() => setOpen(true)}
+ >Details
+ </Badge>
+
+ <Drawer open={open} onOpenChange={setOpen}>
+ <DrawerContent>
+ <DrawerHeader>
+ <DrawerTitle>{cashout_method.name} Details</DrawerTitle>
+ <DrawerDescription>
+ <div dangerouslySetInnerHTML={{__html: cashout_method.description}}/>
+ </DrawerDescription>
+ </DrawerHeader>
+ </DrawerContent>
+ </Drawer>
+
</Card>
)
}
-const CashoutMethodsPage: React.FC<GRLWidgetSettings> = ({settings}) => {
- const [cashoutMethods, setCashoutMethods] = useState([]);
- useEffect(() => {
- const x = new WalletApi();
- x.getCashoutMethodsProductIdCashoutMethodsGet(settings.bpid, settings.bpuid)
- .then(res => {
- const data: CashoutMethodsResponse = res.data;
- setCashoutMethods(data.cashout_methods);
- })
- .catch(err => console.log(err));
- }, []); // ← empty array means "run once"
+const CashoutMethodsPage = () => {
+ const variableCashoutMethods = useSelector(selectVariableCashoutMethods)
+ const fixedCashoutMethods = useSelector(selectFixedCashoutMethods)
+ const wallet: UserWalletBalance = useAppSelector(state => state.wallet)
+
return (
- <div className="grid grid-cols-3 gap-1 p-1">
- {
- cashoutMethods.map((m, index) => {
- return <CashoutMethodPreview key={index} cashout_method={m}/>;
- })
- }
- </div>
- );
+ <>
+ <p>Your balance is <strong>{formatCentsToUSD(wallet.amount)}</strong>.</p>
+ <p>You can redeem <strong>{formatCentsToUSD(wallet.redeemable_amount)}</strong> now.</p>
+ <p><small>(a portion of each survey is delayed by 30 days)</small></p>
+
+ <Tabs defaultValue="dynamic">
+ <TabsList
+ className="cursor-pointer"
+ >
+ <TabsTrigger value="dynamic">Variable</TabsTrigger>
+ <TabsTrigger value="fixed">Fixed</TabsTrigger>
+ </TabsList>
+
+ <TabsContent value="dynamic">
+ <div className="grid grid-cols-3 gap-1 p-1">
+ {
+ variableCashoutMethods.map((m, index) => {
+ return <CashoutMethodPreview key={index} cashout_method={m}/>;
+ })
+ }
+ </div>
+ </TabsContent>
+ <TabsContent value="fixed">
+ <div className="grid grid-cols-3 gap-1 p-1">
+ {
+ fixedCashoutMethods.map((m, index) => {
+ return <CashoutMethodPreview key={index} cashout_method={m}/>;
+ })
+ }
+ </div>
+ </TabsContent>
+ </Tabs>
+ </>
+ )
}
+
export {CashoutMethodsPage} \ No newline at end of file