diff --git a/src/pages/ownership.tsx b/src/pages/ownership.tsx index daa6edb69..acc4d0eb4 100644 --- a/src/pages/ownership.tsx +++ b/src/pages/ownership.tsx @@ -5,8 +5,9 @@ import { GLOBAL_CONSTANTS } from '@src/config-global.ts'; import { OgMetaTags } from '@src/components/og-meta-tags.tsx'; import Header from '@src/layouts/dashboard/header.tsx'; import HeaderContent from '@src/layouts/dashboard/header-content.tsx'; -import { OwnershipView } from '@src/sections/ownership/index'; +import { OwnershipView } from '@src/sections/ownership'; import { useSelector } from 'react-redux'; +import {WithAuth} from "@src/components/should-login/withAuth.tsx" // ---------------------------------------------------------------------- @@ -31,9 +32,9 @@ export default function FileManagerPage() { {canViewSection(sessionData) ? ( <>
- +
- + ) : ( diff --git a/src/sections/marketing/types.ts b/src/sections/marketing/types.ts index 3bf076e2b..980f51913 100644 --- a/src/sections/marketing/types.ts +++ b/src/sections/marketing/types.ts @@ -7,7 +7,7 @@ export interface CampaignType { expiration: number; } -export interface CampaignTableRowType extends CampaignType {} +export type CampaignTableRowType = CampaignType export interface CampaignTableRowProps { row: CampaignTableRowType; @@ -15,8 +15,8 @@ export interface CampaignTableRowProps { } export interface CampaignModalContentProps { + onConfirm?: () => void; onClose: () => void; - onConfirm: () => void; } export interface CampaignConfiguredIndicatorStateProps { diff --git a/src/sections/ownership/CONSTANTS.tsx b/src/sections/ownership/CONSTANTS.tsx new file mode 100644 index 000000000..25fd4fdf9 --- /dev/null +++ b/src/sections/ownership/CONSTANTS.tsx @@ -0,0 +1,27 @@ +import { COLORS } from '@src/sections/finance/CONSTANTS.tsx'; + +export const OWNERSHIP_TABLE_HEAD = [ + { id: 'name', label: 'Publication', minWidth: 300 }, + { id: 'limit', label: 'Policies', minWidth: 100}, + { id: 'budget', label: 'Restrictions', minWidth: 100}, + { id: 'status', label: 'Status', minWidth: 100 }, +]; + +export const LBL_STATUS_COLORS = { + active: COLORS.success, + deactivated: COLORS.warning, +}; + +export const LBL_TYPES_TEXTS = [ + {id: 1,name: "Subscription"}, + {id: 2,name: "Rent"}, + {id: 3,name: "Buy",} +]; + +export const LBL_REGIONS_TEXTS = [ + {id: 1,name: "US"}, + {id: 2,name: "EU"}, + {id: 3,name: "ASIA"}, + {id: 4,name: "LATAM"}, + {id: 5,name: "AFRICA"}, +] diff --git a/src/sections/ownership/components/ownership-create.tsx b/src/sections/ownership/components/ownership-create.tsx new file mode 100644 index 000000000..6793b3130 --- /dev/null +++ b/src/sections/ownership/components/ownership-create.tsx @@ -0,0 +1,53 @@ +// MUI IMPORTS +import Button from '@mui/material/Button'; + +// LOCAL IMPORTS +import Iconify from '@src/components/iconify'; +import OwnershipModal from '@src/components/modal'; +import { useBoolean } from '@src/hooks/use-boolean'; +import { FC } from 'react'; +import { CampaignCreateProps } from '@src/sections/marketing/types.ts'; +import {OwnershipModalContent} from "@src/sections/ownership/components/ownership-modal-content.tsx" + +// ---------------------------------------------------------------------- + +const OwnershipCreate: FC = ({ onSuccess }) => { + const ownershipConfirmPublish = useBoolean(); + + const handleClose = () => { + ownershipConfirmPublish.onFalse?.(); + }; + + const handleClick = () => { + ownershipConfirmPublish.onTrue?.(); + }; + + const handleConfirm = () => { + onSuccess?.(); + ownershipConfirmPublish.onFalse(); + }; + + return ( + <> + + } + /> + + ); +}; + +export {OwnershipCreate}; diff --git a/src/sections/ownership/components/ownership-modal-content.tsx b/src/sections/ownership/components/ownership-modal-content.tsx new file mode 100644 index 000000000..1904072e3 --- /dev/null +++ b/src/sections/ownership/components/ownership-modal-content.tsx @@ -0,0 +1,138 @@ +import LoadingButton from "@mui/lab/LoadingButton"; +import NeonPaper from '@src/sections/publication/components/neon-paper-container.tsx'; +import { FC, useState } from 'react'; +import { + Button, + DialogActions, + Divider, + + Box, Typography, TextField, Stack, +} from '@mui/material' +import {notifyError, notifyInfo, notifySuccess} from '@notifications/internal-notifications.ts' +import { SUCCESS } from '@notifications/success.ts'; +import { CampaignModalContentProps } from '@src/sections/marketing/types.ts'; +import Iconify from "@src/components/iconify" +import {INFO} from "@notifications/info.ts" +import {ERRORS} from "@notifications/errors.ts" +import {replacePrefix} from "@src/utils/wallet.ts" +import {useRegisterAsset} from "@src/hooks/protocol/use-register-asset.ts" +import {useSubmitAssetToLens} from "@src/hooks/use-submit-assets-to-lens.ts" +import {useGetAssetOwner} from "@src/hooks/protocol/use-get-asset-owner.ts" +// ---------------------------------------------------------------------- + +const OwnershipModalContent: FC = ({ onClose, onConfirm }) => { + const [hashes, setHashes] = useState(''); + const { registerAsset } = useRegisterAsset(); + const { submitAssetToLens } = useSubmitAssetToLens(); + const { fetchOwnerAddress } = useGetAssetOwner(); + const [isProcessing, setIsProcessing] = useState(false); + const [progress, setProgress] = useState(0); + const hashesArray = hashes.split(',') + .map(h => h.trim()) + .filter(Boolean); + + const RainbowEffect = isProcessing ? NeonPaper : Box; + + // Validate fields, calculate expiration in seconds, and call the create function from the hook + const handleRegister = async () => { + if (!hashes) return; + + setProgress(1); + setIsProcessing(true); + + try { + for (const [index, hash] of hashesArray.entries()) { + try { + // 1. Report progress + notifyInfo(INFO.REGISTER_OWNERSHIP_PROGRESS, { + index: index + 1, + total: hashesArray.length, + options: { autoHideDuration: 3000 } + }, '', { autoHideDuration: 3000 }); + setProgress(index + 1); + + const isTaken = await fetchOwnerAddress(hash); + + if (isTaken) { + notifyError(ERRORS.ASSET_ALREADY_REGISTERED_ERROR); + continue; + } + + if (!isTaken) { + // 2. Register ownership (if it fails, it does not continue) + await registerAsset(hash); + } + + // 3. Upload to Lens only if registration was successful + await submitAssetToLens(replacePrefix(hash)); + notifySuccess(SUCCESS.OWNERSHIP_REGISTERED_SUCCESSFULLY, { count: index + 1 }); + } catch (error) { + notifyError(ERRORS.ASSET_OWNERSHIP_REGISTER_ERROR, { hash: `${index + 1}/${hashesArray.length}` }); + continue; // Continue with the next hash + } + } + } catch (error) { + notifyError(ERRORS.ASSET_OWNERSHIP_REGISTER_ERROR); + } finally { + setIsProcessing(false); + onClose(); + } + }; + + return ( + <> + + + + + Enter the hash(es) of the content you want to register + + + You can enter multiple hashes separated by commas. + + + setHashes(e.target.value)} + placeholder="e.g., hash1,hash2,hash3" + disabled={isProcessing} + /> + + + + + + + + } + > + Confirm + + + + + ); +}; + +export {OwnershipModalContent}; diff --git a/src/sections/ownership/components/ownership-settings-modal-content.tsx b/src/sections/ownership/components/ownership-settings-modal-content.tsx new file mode 100644 index 000000000..41f56b4a3 --- /dev/null +++ b/src/sections/ownership/components/ownership-settings-modal-content.tsx @@ -0,0 +1,170 @@ +import { FC, useState, useMemo, useEffect } from 'react'; +import { fetchAssetSettings, upsertAssetSettings } from '@src/utils/supabase-actions'; +import Box from "@mui/material/Box"; +import Grid from '@mui/material/Grid'; +import Divider from '@mui/material/Divider'; +import Typography from '@mui/material/Typography'; +import InputLabel from '@mui/material/InputLabel'; +import ListItemText from '@mui/material/ListItemText'; +import Select from '@mui/material/Select'; +import Checkbox from '@mui/material/Checkbox'; +import TextField from "@mui/material/TextField" +import LoadingButton from "@mui/lab/LoadingButton"; +import NeonPaper from "@src/sections/publication/components/neon-paper-container.tsx"; +import {Button, FormControl, DialogActions, LinearProgress, MenuItem} from '@mui/material' +import {OwnershipSettingsModalContentProps} from "@src/sections/ownership/types.ts" +import {LBL_REGIONS_TEXTS, LBL_TYPES_TEXTS} from "@src/sections/ownership/CONSTANTS.tsx" +import {randomKey} from "@src/utils/uuidv4.ts" +// ---------------------------------------------------------------------- +const OwnershipSettingsModalContent: FC = (props) => { + const { onClose, onConfirm, assetData, } = props; + const [loading, setLoading] = useState(false); + const [formValues, setFormValues] = useState({ type: '', region: [] }); + const { name, id } = assetData; + + const RainbowEffect = loading ? NeonPaper : Box; + + useEffect(() => { + const loadAssetSettings = async () => { + setLoading(true); + const { data, error } = await fetchAssetSettings(String(id)); + if (data) { + const parsedRegions = JSON.parse(data.region); + const uniqueRegions = [...new Set(parsedRegions)]; + // @ts-expect-error NO error handling + setFormValues({ type: data.type, region: uniqueRegions }); + } else if (error) { + console.error('Error fetching asset settings:', error); + } + setLoading(false); + }; + + loadAssetSettings(); + }, [id]); + + // Validate that each field has a value greater or equal to 1 + const isFormValid = useMemo(() => { + // Verify that each field has a value greater or equal to 1 + return formValues.type !== '' && formValues.region.length > 0; + }, [formValues]); + + const handleOnConfirm = async () => { + if (!isFormValid) return; + + setLoading(true); + try { + const { error } = await upsertAssetSettings({ + asset_id: String(id), + name, + type: formValues.type, + region: JSON.stringify(formValues.region) + }); + if (error) { + throw new Error(error); + } + onConfirm?.(); + } catch (err) { + console.error('Error configuring asset settings:', err); + } finally { + setLoading(false); + } + }; + + const flattenArray = (arr) => { + return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenArray(val)) : acc.concat(val), []); + }; + + const handleSelectChange = (event) => { + const { name, value } = event.target; + const flattenedValue = Array.isArray(value) ? flattenArray(value) : [value]; + const uniqueValues = [...new Set(flattenedValue)]; + setFormValues((prev) => ({ + ...prev, + [name]: name === 'region' ? uniqueValues : value, + })); + }; + + return ( + <> + {loading && } + + + + + Define several settings for the publication like access type and region availability. + + + + + + {LBL_TYPES_TEXTS.map((option) => ( + + {option.name} + + ))} + + + + + Choose the region where content is available + + + + Region + + + + + + + + + + + + Confirm + + + + + ); +}; + +export {OwnershipSettingsModalContent}; diff --git a/src/sections/ownership/components/ownership-settings-modal.tsx b/src/sections/ownership/components/ownership-settings-modal.tsx new file mode 100644 index 000000000..aa64ef55e --- /dev/null +++ b/src/sections/ownership/components/ownership-settings-modal.tsx @@ -0,0 +1,36 @@ +import { FC } from "react"; +import SettingsModal from '@src/components/modal'; +import {OwnershipSettingsModalContent} from "./ownership-settings-modal-content.tsx"; +import {OwnershipSettingsModalProps} from "@src/sections/ownership/types.ts" + +// ---------------------------------------------------------------------- + +const OwnershipSettingsModal: FC = (props) => { + const { open, onSuccess, onClose, assetData } = props; + + const handleClose = () => { + onClose?.(); + }; + + const handlSuccess = () => { + onSuccess?.(); + handleClose(); + }; + + return ( + + } + /> + ); +}; + +export {OwnershipSettingsModal}; diff --git a/src/sections/ownership/components/ownership-table-row.tsx b/src/sections/ownership/components/ownership-table-row.tsx new file mode 100644 index 000000000..4a4938ebf --- /dev/null +++ b/src/sections/ownership/components/ownership-table-row.tsx @@ -0,0 +1,183 @@ +// MUI IMPORTS +import Typography from '@mui/material/Typography'; +import TableRow from '@mui/material/TableRow'; +import TableCell from '@mui/material/TableCell'; +import ListItemText from '@mui/material/ListItemText'; +import Grid from '@mui/material/Grid'; +import Switch from '@mui/material/Switch'; +import { IconButton, MenuItem } from '@mui/material'; + +// LOCAL IMPORTS +import Iconify from '@src/components/iconify'; +import TextMaxLine from "@src/components/text-max-line"; +import { OwnershipSettingsModal} from "@src/sections/ownership/components/ownership-settings-modal.tsx"; +import CustomPopover, { usePopover } from '@src/components/custom-popover'; +import { capitalizeFirstLetter } from '@src/utils/text-transform.ts'; +import { useBoolean } from '@src/hooks/use-boolean'; +import {LBL_STATUS_COLORS} from '@src/sections/ownership/CONSTANTS.tsx' +import {OwnershipTableRowProps} from "@src/sections/ownership/types.ts" +import Stack from "@mui/material/Stack" +import Image from "@src/components/image" +import { OwnershipTimelineModal } from './ownership-timeline-modal'; +// ---------------------------------------------------------------------- +const OwnershipTableRow = ({ row, selected }: Readonly) => { + const { name, image, id, description, status, restrictions, police } = row; + const popover = usePopover(); + const settingsModal = useBoolean(); + const timelineModal = useBoolean(); + const onSettingRow = () => { + settingsModal.onTrue(); + }; + + const onTimelineRow = () => { + timelineModal.onTrue(); + } + + const handlePauseToggle = async (checked: boolean) => { + try { + console.log('handlePauseToggle', checked); + popover.onClose(); + } catch (error) { + console.error(error); + } + }; + + const getColorByKey = (colorObj: Record, key: string): string => { + return (key && colorObj[key as keyof typeof colorObj]) || ''; + }; + + const renderPrimary = ( + <> + + + + {name} + {name}} + secondary={{description}} + primaryTypographyProps={{ typography: 'body2' }} + secondaryTypographyProps={{ + component: 'span', + color: 'text.disabled', + }} + /> + + + + + + + + + + + + + + + {capitalizeFirstLetter(status.name ?? '')} + + + + + + + + + + { + popover.onClose(); + }} + arrow="right-top" + sx={{ width: 160 }} + > + { + onSettingRow(); + popover.onClose(); + }} + > + + Settings + + { + onTimelineRow() + popover.onClose(); + }} + > + + History + + e.stopPropagation()} + > + + + Active + + + { + await handlePauseToggle(!event.target.checked); + }} + disabled={false} + /> + + + + {}} + assetData={{ + id: id, + name: name, + }} + /> + {}} + assetData={{ + name: name, + }} + /> + + ); + + return <>{renderPrimary}; +} + +export { OwnershipTableRow }; diff --git a/src/sections/ownership/components/ownership-table.tsx b/src/sections/ownership/components/ownership-table.tsx new file mode 100644 index 000000000..f9faf4ad7 --- /dev/null +++ b/src/sections/ownership/components/ownership-table.tsx @@ -0,0 +1,104 @@ +// REACT IMPORTS +import { FC } from 'react'; + +// MUI IMPORTS +import TableBody from '@mui/material/TableBody'; +import TableCell from "@mui/material/TableCell"; +import TableRow from "@mui/material/TableRow"; +import { Box, Table, TableContainer } from '@mui/material'; + +// LOCAL IMPORTS +import Scrollbar from '@src/components/scrollbar'; +import { + emptyRows, + TableEmptyRows, + TableHeadCustom, + TableNoData, + TablePaginationCustom, + useTable, +} from '@src/components/table'; +import { LoadingScreen } from "@src/components/loading-screen"; +import { COLORS } from '@src/layouts/config-layout'; +import {OwnershipTableProps} from "@src/sections/ownership/types.ts" +import {OWNERSHIP_TABLE_HEAD} from "@src/sections/ownership/CONSTANTS.tsx" +import {OwnershipTableRow} from "@src/sections/ownership/components/ownership-table-row.tsx" + +// ---------------------------------------------------------------------- + +const OwnershipTable: FC = (args) => { + const { assets, loading } = args; + + const table = useTable({ + defaultOrder: 'desc', + defaultOrderBy: 'createdAt', + }); + + const notFound = !assets.length && !loading; + const denseHeight = table.dense ? 52 : 72; + + return ( + <> + + + + + + + {loading ? ( + + + + + + ) : ( + <> + {assets + .slice( + table.page * table.rowsPerPage, + table.page * table.rowsPerPage + table.rowsPerPage + ) + .map((row) => ( + + ))} + + + + )} + +
+
+
+
+ + + + ); +}; + +export default OwnershipTable; diff --git a/src/sections/ownership/components/ownership-timeline-modal-content.tsx b/src/sections/ownership/components/ownership-timeline-modal-content.tsx new file mode 100644 index 000000000..6c3ed16ce --- /dev/null +++ b/src/sections/ownership/components/ownership-timeline-modal-content.tsx @@ -0,0 +1,90 @@ +import Grid from '@mui/material/Grid'; +import Divider from '@mui/material/Divider'; +import {FC, useEffect, useState} from 'react' +import {Button, DialogActions, LinearProgress} from '@mui/material' +import { + OwnershipSettingsModalContentProps, + OwnershipTimelineItemProps, +} from "@src/sections/ownership/types.ts" +import Timeline from '@mui/lab/Timeline'; +import {timelineItemClasses} from '@mui/lab/TimelineItem' + +import {OwnershipTimelineItem} from "@src/sections/ownership/components/ownership-timeline-modal-item.tsx" + +const list: OwnershipTimelineItemProps[] = [ + { + id: '1', + title: '0x9d1f...4751DD listed for', + time: new Date(), + type: 'order1', + }, + { + id: '2', + title: '0x9d1f...4751DD transferred to 0x9d1f...4751DD', + time: new Date(), + type: 'order2', + }, + { + id: '3', + title: '0x9d1f...4751DD transferred to 0x212121....', + time: new Date(), + type: 'order2', + }, + { + id: '4', + title: '0x9d1f...4751DD transferred to 0x9d1f...4751DD', + time: new Date(), + type: 'order2', + }, + ] + +// ---------------------------------------------------------------------- +const OwnershipTimelineModalContent: FC = (props) => { + const { onClose } = props; + const [loading, setLoading] = useState(false); + + useEffect(() => { + setLoading(true); + + setTimeout(() => { + setLoading(false); + }, 1000); + }, []) + + return ( + <> + + + + + {loading && } + + + + {list.map((item, index) => ( + + ))} + + + + + + + + + + ); +}; + +export {OwnershipTimelineModalContent}; diff --git a/src/sections/ownership/components/ownership-timeline-modal-item.tsx b/src/sections/ownership/components/ownership-timeline-modal-item.tsx new file mode 100644 index 000000000..dd4ef8e73 --- /dev/null +++ b/src/sections/ownership/components/ownership-timeline-modal-item.tsx @@ -0,0 +1,36 @@ +import {OwnershipTimelineItemsProps} from "@src/sections/ownership/types.ts" +import TimelineItem from "@mui/lab/TimelineItem" +import TimelineSeparator from "@mui/lab/TimelineSeparator" +import TimelineDot from "@mui/lab/TimelineDot" +import TimelineConnector from "@mui/lab/TimelineConnector" +import TimelineContent from "@mui/lab/TimelineContent" +import {Typography} from "@mui/material" +import {fDateTime} from "@src/utils/format-time.ts" + +const OwnershipTimelineItem = ({ item, lastTimeline }: OwnershipTimelineItemsProps)=> { + const { type, title, time } = item; + return ( + + + + {lastTimeline ? null : } + + + + {title} + + + {fDateTime(time)} + + + + ); +} + +export {OwnershipTimelineItem}; diff --git a/src/sections/ownership/components/ownership-timeline-modal.tsx b/src/sections/ownership/components/ownership-timeline-modal.tsx new file mode 100644 index 000000000..ea5a95565 --- /dev/null +++ b/src/sections/ownership/components/ownership-timeline-modal.tsx @@ -0,0 +1,36 @@ +import { FC } from "react"; +import SettingsModal from '@src/components/modal'; +import {OwnershipSettingsModalProps} from "@src/sections/ownership/types.ts" +import {OwnershipTimelineModalContent} from "@src/sections/ownership/components/ownership-timeline-modal-content.tsx" + +// ---------------------------------------------------------------------- + +const OwnershipTimelineModal: FC = (props) => { + const { open, onSuccess, onClose, assetData } = props; + + const handleClose = () => { + onClose?.(); + }; + + const handlSuccess = () => { + onSuccess?.(); + handleClose(); + }; + + return ( + + } + /> + ); +}; + +export {OwnershipTimelineModal}; diff --git a/src/sections/ownership/index.tsx b/src/sections/ownership/index.tsx index df9002fdf..12d60a630 100644 --- a/src/sections/ownership/index.tsx +++ b/src/sections/ownership/index.tsx @@ -1 +1 @@ -export { default as OwnershipView } from '@src/sections/ownership/views/ownership-view.tsx'; +export { OwnershipView } from '@src/sections/ownership/views/ownership-view.tsx'; diff --git a/src/sections/ownership/types.ts b/src/sections/ownership/types.ts new file mode 100644 index 000000000..03df9fac8 --- /dev/null +++ b/src/sections/ownership/types.ts @@ -0,0 +1,65 @@ +export interface OwnershipTableProps { + assets: OwnershipAsset[]; + loading: boolean; +} + +export interface OwnershipCreateProps { + onSuccess?: () => void; +} + +export interface OwnershipTableRowProps { + row: OwnershipAsset; + selected: boolean; +} + +export interface AssetPolicy { + name: string; +} + +export interface AssetStatus { + name: string; +} + +export interface AssetType { + name: string; +} + +export interface OwnershipAsset { + id: number; + name: string; + image: string; + description: string; + police: AssetPolicy; + restrictions: boolean; + status: AssetStatus +} + +export interface OwnershipSettingsModalProps { + open: boolean; + onClose?: () => void; + onSuccess?: () => void; + assetData: { + id: number; + name: string; + }; +} +export interface OwnershipSettingsModalContentProps { + onClose?: () => void; + onConfirm?: () => void; + assetData: { + id: number + name: string; + }; +} + +export interface OwnershipTimelineItemProps { + id: string; + title: string; + time: Date; + type: string; +} + +export interface OwnershipTimelineItemsProps { + item: OwnershipTimelineItemProps; + lastTimeline: boolean; +} diff --git a/src/sections/ownership/views/ownership-view.tsx b/src/sections/ownership/views/ownership-view.tsx index 343c90090..b0f9e2801 100644 --- a/src/sections/ownership/views/ownership-view.tsx +++ b/src/sections/ownership/views/ownership-view.tsx @@ -1,7 +1,47 @@ -import Container from "@mui/material/Container"; -import Grid from "@mui/material/Unstable_Grid2"; -import Stack from "@mui/material/Stack"; -import OwnershipProcess from "@src/sections/ownership/components/ownership-process.tsx"; +import Grid from '@mui/material/Grid'; +import Container from '@mui/material/Container'; +import OwnershipTable from '@src/sections/ownership/components/ownership-table.tsx'; +import {OwnershipCreate} from "@src/sections/ownership/components/ownership-create.tsx" +import { AssetPolicy, AssetStatus, OwnershipAsset } from '../types'; +import {CustomRandom} from "@src/utils/random.ts" + +const assetPolicies: AssetPolicy[] = [ + { name: 'Subscription' }, +] + +const assetStatuses: AssetStatus[] = [ + { name: 'Active' }, + { name: 'Deactivated' }, +] + +const movies = [ + {movie: 'Matrix Underground', image: 'https://i.blogs.es/8b8798/06-06-matrix/1366_2000.jpg'}, + {movie: 'Titanic II', image: 'https://resizing.flixster.com/jt582j6FBD6irE_K_rGPlcSrii4=/206x305/v2/https://resizing.flixster.com/-XZAfHZM39UwaGJIFWKAE8fS0ak=/v3/t/assets/p8175397_p_v10_ab.jpg'}, + {movie: 'Gladiator IV', image: 'https://media.sitioandino.com.ar/p/e9e4d7e62c53b7ba3b3cd6b85233a3c5/adjuntos/335/imagenes/000/737/0000737580/1200x630/smart/gladiadorpng.png'}, + {movie: 'El Chavo and Spiderman', image: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR5A7xUMmL75NohLvMjgv9m0o6Ugqt_OQPk5w&s'}, +] + +const generateRandomAsset = (count: number): OwnershipAsset[] => { + const assets: OwnershipAsset[] = []; + for (let i = 0; i < count; i++) { + const randomPolicy = assetPolicies[Math.floor(CustomRandom.get() * assetPolicies.length)]; + const randomStatus = assetStatuses[Math.floor(CustomRandom.get() * assetStatuses.length)]; + const randomName = movies[Math.floor(CustomRandom.get() * movies.length)]; + + const asset: OwnershipAsset = { + id: i + 1, + name: randomName.movie, + image: randomName.image, + description: `Description for ${randomName.movie}`, + police: randomPolicy, + restrictions: CustomRandom.get() < 0.5, + status: randomStatus + }; + + assets.push(asset); + } + return assets; +} const OwnershipView = () => { return ( @@ -12,21 +52,24 @@ const OwnershipView = () => { maxWidth: '100% !important', }} > - - - - - - + + {}} /> + + + + - ) -} + ); +}; -export default OwnershipView; +export {OwnershipView} diff --git a/src/utils/random.ts b/src/utils/random.ts new file mode 100644 index 000000000..a4f10eee2 --- /dev/null +++ b/src/utils/random.ts @@ -0,0 +1,33 @@ +/** + * CustomRandom is an object implementing a linear congruential generator (LCG) for generating pseudo-random numbers. + * It uses specific LCG parameters to calculate random values and provides methods for retrieving these values. + * + * Properties: + * - seed: The initial seed used to produce random numbers. It is set to the current time in milliseconds. + * - a: Multiplier parameter used in the LCG formula. + * - c: Increment parameter used in the LCG formula. + * - m: Modulus parameter used in the LCG formula (set to 2^32). + * + * Methods: + * - next: Computes the next pseudo-random number in the sequence as per the LCG formula. + * Updates the seed value and returns a number between 0 and 1. + * - getRandomDecimal: Generates a pseudo-random decimal between 0 and 1, rounded down to one decimal place. + */ +export const CustomRandom = { + seed: new Date().getTime(), + + // LCG parameters + a: 1664525, + c: 1013904223, + m: Math.pow(2, 32), + + next() { + this.seed = (this.a * this.seed + this.c) % this.m; + return this.seed / this.m; + }, + + get() { + const randomValue = this.next(); + return Math.floor(randomValue * 10) / 10; + } +}; diff --git a/src/utils/supabase-actions.ts b/src/utils/supabase-actions.ts index 44028d543..ad60bd1cb 100644 --- a/src/utils/supabase-actions.ts +++ b/src/utils/supabase-actions.ts @@ -218,3 +218,30 @@ export const checkIfEmailAlreadyInvited = async ( return { invited: false, error: err.message }; } }; + + +export const fetchAssetSettings = async (asset_id: string) => { + try { + const { data, error } = await supabase + .from('ownership') + .select('type, region') + .eq('asset_id', asset_id) + .single(); + + return { data, error: error ? error.message : null }; + } catch (err: any) { + return { data: null, error: err.message }; + } +}; + +export const upsertAssetSettings = async (assetSettings: { asset_id: string, name: string, type: string, region: string }) => { + try { + const { data, error } = await supabase + .from('ownership') + .upsert(assetSettings, { onConflict: ['asset_id'] }); + + return { data, error: error ? error.message : null }; + } catch (err: any) { + return { data: null, error: err.message }; + } +};