diff --git a/src/app/AIStrategyBuilder/page.js b/src/app/AIStrategyBuilder/page.jsx similarity index 100% rename from src/app/AIStrategyBuilder/page.js rename to src/app/AIStrategyBuilder/page.jsx diff --git a/src/app/Brokers/page.js b/src/app/Brokers/page.jsx similarity index 100% rename from src/app/Brokers/page.js rename to src/app/Brokers/page.jsx diff --git a/src/app/Positions/page.js b/src/app/Positions/page.jsx similarity index 100% rename from src/app/Positions/page.js rename to src/app/Positions/page.jsx diff --git a/src/app/Scan_Tracks/page.js b/src/app/Scan_Tracks/page.jsx similarity index 100% rename from src/app/Scan_Tracks/page.js rename to src/app/Scan_Tracks/page.jsx diff --git a/src/app/layout.js b/src/app/layout.js index 25eee67..5787852 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -25,11 +25,9 @@ export const metadata = { export default function RootLayout({ children }) { return ( - -
+
-
-
{children}
+
{children}
diff --git a/src/app/page.js b/src/app/page.jsx similarity index 100% rename from src/app/page.js rename to src/app/page.jsx diff --git a/src/components/brokers/BrokerAvatar.js b/src/components/brokers/BrokerAvatar.jsx similarity index 100% rename from src/components/brokers/BrokerAvatar.js rename to src/components/brokers/BrokerAvatar.jsx diff --git a/src/components/brokers/BrokerForm.js b/src/components/brokers/BrokerForm.js deleted file mode 100644 index 9e7b057..0000000 --- a/src/components/brokers/BrokerForm.js +++ /dev/null @@ -1,86 +0,0 @@ -'use client'; - -import FormInput from '@/components/ui/FormInput'; -import FormSelect from '@/components/ui/FormSelect'; -import { BROKER_OPTIONS, STATUS_OPTIONS } from '@/constants/brokers'; - -export default function BrokerForm({ formData, onChange, mode, selectedBroker }) { - return ( - <> -

- Choose your preferred exchange to add a broker. -

- -
-

Broker Details

- - onChange({ ...formData, name: val })} - placeholder="Enter a Name" - required - /> - - onChange({ ...formData, broker: val })} - options={BROKER_OPTIONS} - placeholder="Select Broker" - /> - - onChange({ ...formData, balance: val })} - placeholder="$0.00" - type="text" - /> - - onChange({ ...formData, status: val })} - options={STATUS_OPTIONS} - placeholder="Select Status" - /> -
- -
-
-

API Details

- {mode === 'edit' ? ( - - ) : ( - - )} -
- - onChange({ ...formData, apiKey: val })} - placeholder="api_key_1234567890abcdef" - helperText={ - mode === 'edit' && selectedBroker - ? `Date Created: ${selectedBroker.dateCreated}` - : '' - } - /> - - onChange({ ...formData, secretKey: val })} - placeholder="sk_412345LH..." - type="password" - /> -
- - ); -} \ No newline at end of file diff --git a/src/components/brokers/BrokerForm.jsx b/src/components/brokers/BrokerForm.jsx new file mode 100644 index 0000000..822da49 --- /dev/null +++ b/src/components/brokers/BrokerForm.jsx @@ -0,0 +1,77 @@ +"use client"; + +import FormInput from "@/components/ui/FormInput"; +import FormSelect from "@/components/ui/FormSelect"; +import { BROKER_OPTIONS } from "@/constants/brokers"; + +export default function BrokerForm({ + formData, + onChange, + mode, + selectedBroker, +}) { + return ( +
+
+

+ Broker Details +

+ + onChange({ ...formData, name: val })} + placeholder="Enter a Name" + className="outline-gray-200" + required + /> + + onChange({ ...formData, broker: val })} + options={BROKER_OPTIONS} + placeholder="Select Broker" + className="outline-gray-200" + /> +
+ +
+
+

API Details

+ {mode === "edit" ? ( + + ) : ( + + )} +
+ + onChange({ ...formData, apiKey: val })} + placeholder="api_key_1234567890abcdef" + helperText={ + mode === "edit" && selectedBroker + ? `Date Created: ${selectedBroker.dateCreated}` + : "" + } + styleEl="bg-gray-50" + /> + + onChange({ ...formData, secretKey: val })} + placeholder="sk_412345LH..." + type="password" + styleEl="bg-gray-50" + /> +
+
+ ); +} diff --git a/src/components/brokers/BrokerManagement.js b/src/components/brokers/BrokerManagement.js deleted file mode 100644 index 4fd8968..0000000 --- a/src/components/brokers/BrokerManagement.js +++ /dev/null @@ -1,224 +0,0 @@ -"use client"; - -import { useState } from "react"; -import BrokerTable from "./BrokerTable"; -import SearchBar from "./SearchBar"; -import StatusFilter from "./StatusFilter"; -import SlidePanel from "@/components/ui/SlidePanel"; -import BrokerForm from "./BrokerForm"; -import { Plus, Download, SlidersHorizontal } from "lucide-react"; -import { filterBrokers, createNewBroker } from "@/utils/brokerHelpers"; -import { INITIAL_BROKERS } from "@/constants/brokers"; - -export default function BrokerManagement() { - // Broker state - const [brokers, setBrokers] = useState(INITIAL_BROKERS); - - // Slide panel state - const [isSlideOpen, setIsSlideOpen] = useState(false); - const [slideMode, setSlideMode] = useState("add"); - const [selectedBroker, setSelectedBroker] = useState(null); - - // Filter state - default to 'active' - const [searchTerm, setSearchTerm] = useState(""); - const [filterStatus, setFilterStatus] = useState("active"); - - // Hidden rows state - const [hiddenRows, setHiddenRows] = useState([]); - - // Form state - const [formData, setFormData] = useState({ - name: "", - broker: "", - apiKey: "", - secretKey: "", - balance: "$0.00", - status: "active", - }); - - // Event handlers - const handleAdd = () => { - setSlideMode("add"); - setFormData({ - name: "", - broker: "", - apiKey: "", - secretKey: "", - balance: "$0.00", - status: "active", - }); - setIsSlideOpen(true); - }; - - const handleEdit = (broker) => { - setSlideMode("edit"); - setSelectedBroker(broker); - setFormData({ - name: broker.name, - broker: broker.broker, - apiKey: broker.apiKey, - secretKey: broker.secretKey, - balance: broker.balance, - status: broker.status, - }); - setIsSlideOpen(true); - }; - - const handleSubmit = () => { - if (slideMode === "add") { - const newBroker = { - ...createNewBroker(formData), - balance: formData.balance, - status: formData.status, - }; - setBrokers([...brokers, newBroker]); - } else if (selectedBroker) { - setBrokers( - brokers.map((b) => - b.id === selectedBroker.id - ? { - ...b, - name: formData.name, - broker: formData.broker, - apiKey: formData.apiKey, - secretKey: formData.secretKey, - balance: formData.balance, - status: formData.status, - } - : b - ) - ); - } - setIsSlideOpen(false); - }; - - const handleDelete = (id) => { - setBrokers(brokers.filter((b) => b.id !== id)); - setHiddenRows(hiddenRows.filter((rowId) => rowId !== id)); - }; - - const toggleStatus = (id) => { - setBrokers( - brokers.map((b) => - b.id === id - ? { ...b, status: b.status === "active" ? "inactive" : "active" } - : b - ) - ); - }; - - const toggleVisibility = (id) => { - setHiddenRows((prev) => - prev.includes(id) ? prev.filter((rowId) => rowId !== id) : [...prev, id] - ); - }; - - const handleExportCSV = () => { - // CSV export logic - const headers = [ - "Name", - "API ID", - "Broker", - "Date Added", - "Status", - "Balance", - ]; - const csvContent = [ - headers.join(","), - ...filteredBrokers.map((b) => - [b.name, b.id, b.broker, b.dateAdded, b.status, b.balance].join(",") - ), - ].join("\n"); - - const blob = new Blob([csvContent], { type: "text/csv" }); - const url = window.URL.createObjectURL(blob); - const a = document.createElement("a"); - a.href = url; - a.download = "brokers.csv"; - a.click(); - }; - - // Filter brokers - const filteredBrokers = filterBrokers(brokers, searchTerm, filterStatus); - - return ( -
- {/* Header */} -
-
-
-

- Brokers / API Management -

-
-
-
- -
- - {/* Filters */} -
-
- - - -
- - - -
- - -
-
-
- - {/* Table */} - - - {/* Slide Panel */} - setIsSlideOpen(false)} - title={slideMode === "add" ? "Add Broker" : "Edit Broker"} - onSubmit={handleSubmit} - onCancel={() => setIsSlideOpen(false)} - submitLabel={slideMode === "add" ? "Add" : "Save"} - > - - -
- -
- ); -} diff --git a/src/components/brokers/BrokerManagement.jsx b/src/components/brokers/BrokerManagement.jsx new file mode 100644 index 0000000..1ad4b05 --- /dev/null +++ b/src/components/brokers/BrokerManagement.jsx @@ -0,0 +1,249 @@ +"use client"; + +import { useState } from "react"; +import BrokerTable from "./BrokerTable"; +import SearchBar from "./SearchBar"; +import StatusFilter from "./StatusFilter"; +import SlidePanel from "@/components/ui/SlidePanel"; +import BrokerForm from "./BrokerForm"; +import { Plus, FilePlus2, Filter, User } from "lucide-react"; +import { filterBrokers, createNewBroker } from "@/utils/brokerHelpers"; +import { INITIAL_BROKERS, subPages } from "@/constants/brokers"; +import { li } from "framer-motion/client"; + +export default function BrokerManagement() { + // Broker state + const [brokers, setBrokers] = useState(INITIAL_BROKERS); + const [activeSubPage, setSubPage] = useState(subPages[0].name); + // Slide panel state + const [isSlideOpen, setIsSlideOpen] = useState(false); + const [slideMode, setSlideMode] = useState("add"); + const [selectedBroker, setSelectedBroker] = useState(null); + + // Filter state - default to 'active' + const [searchTerm, setSearchTerm] = useState(""); + const [filterStatus, setFilterStatus] = useState("active"); + + // Hidden rows state + const [hiddenRows, setHiddenRows] = useState([]); + + // Form state + const [formData, setFormData] = useState({ + name: "", + broker: "", + apiKey: "", + secretKey: "", + balance: "$0.00", + status: "active", + }); + + // Event handlers + const handleAdd = () => { + setSlideMode("add"); + setFormData({ + name: "", + broker: "", + apiKey: "", + secretKey: "", + balance: "$0.00", + status: "active", + }); + setIsSlideOpen(true); + }; + + const handleEdit = (broker) => { + setSlideMode("edit"); + setSelectedBroker(broker); + setFormData({ + name: broker.name, + broker: broker.broker, + apiKey: broker.apiKey, + secretKey: broker.secretKey, + balance: broker.balance, + status: broker.status, + }); + setIsSlideOpen(true); + }; + + const handleSubmit = () => { + if (slideMode === "add") { + const newBroker = { + ...createNewBroker(formData), + balance: formData.balance, + status: formData.status, + }; + setBrokers([...brokers, newBroker]); + } else if (selectedBroker) { + setBrokers( + brokers.map((b) => + b.id === selectedBroker.id + ? { + ...b, + name: formData.name, + broker: formData.broker, + apiKey: formData.apiKey, + secretKey: formData.secretKey, + balance: formData.balance, + status: formData.status, + } + : b + ) + ); + } + setIsSlideOpen(false); + }; + + const handleDelete = (id) => { + setBrokers(brokers.filter((b) => b.id !== id)); + setHiddenRows(hiddenRows.filter((rowId) => rowId !== id)); + }; + + const toggleStatus = (id) => { + setBrokers( + brokers.map((b) => + b.id === id + ? { ...b, status: b.status === "active" ? "inactive" : "active" } + : b + ) + ); + }; + + const toggleVisibility = (id) => { + setHiddenRows((prev) => + prev.includes(id) ? prev.filter((rowId) => rowId !== id) : [...prev, id] + ); + }; + + const handleExportCSV = () => { + // CSV export logic + const headers = [ + "Name", + "API ID", + "Broker", + "Date Added", + "Status", + "Balance", + ]; + const csvContent = [ + headers.join(","), + ...filteredBrokers.map((b) => + [b.name, b.id, b.broker, b.dateAdded, b.status, b.balance].join(",") + ), + ].join("\n"); + + const blob = new Blob([csvContent], { type: "text/csv" }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = "brokers.csv"; + a.click(); + }; + + // Filter brokers + const filteredBrokers = filterBrokers(brokers, searchTerm, filterStatus); + + return ( +
+
+
+
+ +

+ Brokers / API Management +

+
+
    + {subPages.map((item) => ( +
  • setSubPage(item.name)} + className={`cursor-pointer pb-4 transition-all duration-300 ${ + activeSubPage === item.name + ? "text-transparent bg-gradient-to-b from-[#00BFA6] to-[#144861] bg-clip-text font-semibold border-b-2 border-[#00BFA6]" + : "text-gray-600" + }`} + > + {item.name} +
  • + ))} +
+
+ {/* main section */} +
+ {/* search row container */} +
+
+ {/* search bar and filter icon */} +
+ + + +
+ {/* active, incative and expired */} + + {/* export and add button */} +
+ + + +
+
+
+ + {/* Table */} + + + {/* Slide Panel */} + setIsSlideOpen(false)} + title={slideMode === "add" ? "Add Broker" : "Edit Broker"} + onSubmit={handleSubmit} + onCancel={() => setIsSlideOpen(false)} + submitLabel={slideMode === "add" ? "Add" : "Save"} + > + + +
+
+
+ ); +} diff --git a/src/components/brokers/BrokerTable.js b/src/components/brokers/BrokerTable.js deleted file mode 100644 index a4ab2ef..0000000 --- a/src/components/brokers/BrokerTable.js +++ /dev/null @@ -1,54 +0,0 @@ -'use client'; - -import TableRow from './TableRow'; - -export default function BrokerTable({ brokers, onEdit, onDelete, onToggleStatus, onToggleVisibility, hiddenRows }) { - return ( -
- - - - - - - - - - - - - - - {brokers.map((broker,index) => ( - - ))} - -
- Name - - API ID - - Broker - - Date Added - - Status - - Balance - - Actions - - On/Off -
-
- ); -} \ No newline at end of file diff --git a/src/components/brokers/BrokerTable.jsx b/src/components/brokers/BrokerTable.jsx new file mode 100644 index 0000000..a47527a --- /dev/null +++ b/src/components/brokers/BrokerTable.jsx @@ -0,0 +1,184 @@ +// 'use client'; + +// import { useState } from 'react'; +// import TableRow from './TableRow'; +// import {EyeOff,Eye} from 'lucide-react'; +// export default function BrokerTable({ brokers, onEdit, onDelete, onToggleStatus, onToggleVisibility, hiddenRows }) { +// const [isHidden,setHidden]=useState(false); +// return ( +//
+// +// +// +// +// +// +// +// +// +// +// +// +// +// +// {brokers.map((broker,index) => ( +// +// ))} +// +//
+// Name +// +// API ID +// +// Broker +// +// Date Added +// +// Status +// +// Balance +// +// +// Actions +// +// On/Off +//
+//
+// ); +// } +'use client'; + +import { useState } from 'react'; +import TableRow from './TableRow'; +import { EyeOff, Eye } from 'lucide-react'; + +export default function BrokerTable({ + brokers, + onEdit, + onDelete, + onToggleStatus, + lastSynced = "May 26, 2025 12:30", + currentPage = 1, + totalPages = 2, + onPageChange +}) { + const [isHidden, setHidden] = useState(false); + + return ( +
+ + + + + + + + + + + + + + + {brokers.map((broker, index) => ( + + ))} + +
+ Name + + API ID + + Broker + + Date Added + + Status + +
+ Balance + +
+
+ Actions + + On/Off +
+ +
+
+ Last Synced: {lastSynced} +
+ +
+ + + {[...Array(totalPages)].map((_, i) => ( + + ))} + + +
+
+
+ ); +} \ No newline at end of file diff --git a/src/components/brokers/SearchBar.js b/src/components/brokers/SearchBar.jsx similarity index 57% rename from src/components/brokers/SearchBar.js rename to src/components/brokers/SearchBar.jsx index 0fe82ca..977cdb7 100644 --- a/src/components/brokers/SearchBar.js +++ b/src/components/brokers/SearchBar.jsx @@ -6,15 +6,15 @@ export default function SearchBar({ searchTerm, onSearchChange }) { return (
onSearchChange(e.target.value)} - className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-500" + className="w-full bg-white p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-1 focus:ring-[#00BFA6]" />
); diff --git a/src/components/brokers/StatusFilter.js b/src/components/brokers/StatusFilter.js deleted file mode 100644 index 161115e..0000000 --- a/src/components/brokers/StatusFilter.js +++ /dev/null @@ -1,36 +0,0 @@ -'use client'; - -import { Filter } from 'lucide-react'; - -export default function StatusFilter({ activeFilter, onFilterChange }) { - const filters = [ - { value: 'all', label: 'All' }, - { value: 'active', label: 'Active' }, - { value: 'inactive', label: 'Inactive' }, - { value: 'expired', label: 'Expired' } - ]; - - return ( - <> - {/* */} -
- {filters.map((filter) => ( - - ))} -
- - ); -} diff --git a/src/components/brokers/StatusFilter.jsx b/src/components/brokers/StatusFilter.jsx new file mode 100644 index 0000000..0ded85a --- /dev/null +++ b/src/components/brokers/StatusFilter.jsx @@ -0,0 +1,32 @@ +"use client"; + +export default function StatusFilter({ activeFilter, onFilterChange }) { + const filters = [ + // { value: 'all', label: 'All' }, + { value: "active", label: "Active" }, + { value: "inactive", label: "Inactive" }, + { value: "expired", label: "Expired" }, + ]; + + return ( + <> +
+ {filters.map((filter) => ( + + ))} +
+ + ); +} diff --git a/src/components/brokers/StatusIndicator.js b/src/components/brokers/StatusIndicator.js deleted file mode 100644 index dbfaa79..0000000 --- a/src/components/brokers/StatusIndicator.js +++ /dev/null @@ -1,11 +0,0 @@ -'use client'; - -import { STATUS_COLORS } from '@/constants/brokers'; - -export default function StatusIndicator({ status }) { - return ( - - ); -} \ No newline at end of file diff --git a/src/components/brokers/StatusIndicator.jsx b/src/components/brokers/StatusIndicator.jsx new file mode 100644 index 0000000..bb7da82 --- /dev/null +++ b/src/components/brokers/StatusIndicator.jsx @@ -0,0 +1,29 @@ +'use client' +import { Check, X, AlertTriangle } from "lucide-react"; + +export default function StatusIndicator({ status }) { + const baseClasses = "w-4 h-4 p-[2px] rounded-full"; // circle look + + switch (status) { + case "active": + return ( +
+ +
+ ); + case "inactive": + return ( +
+ +
+ ); + case "expired": + return ( +
+ +
+ ); + default: + return null; + } +} diff --git a/src/components/brokers/TableRow.js b/src/components/brokers/TableRow.js deleted file mode 100644 index 1c268fb..0000000 --- a/src/components/brokers/TableRow.js +++ /dev/null @@ -1,134 +0,0 @@ -// 'use client'; - -// import { Edit2, Trash2, Eye, EyeOff } from 'lucide-react'; -// import BrokerAvatar from './BrokerAvatar'; -// import StatusIndicator from './StatusIndicator'; -// import ToggleSwitch from '@/components/ui/ToggleSwitch'; - -// export default function TableRow({ index,broker, onEdit, onDelete, onToggleStatus, onToggleVisibility, isHidden }) { -// const BrokerData=isHidden?{name:"---",id:'---',dateAdded:'---',balance:"---",}:broker; -// // if (isHidden) broker={name:"---",id:'---',dateAdded:'---'}; - -// return ( -// -// -// {BrokerData.name} -// -// -// {BrokerData.id} -// -// -// -// -// -// {BrokerData.dateAdded} -// -// -// -// -// -// {BrokerData.balance} -// -// -//
-// -// -// -//
-// -// -// onToggleStatus(broker.id)} -// /> -// -// -// ); -// } -'use client'; - -import { Edit2, Trash2, Eye, EyeOff } from 'lucide-react'; -import BrokerAvatar from './BrokerAvatar'; -import StatusIndicator from './StatusIndicator'; -import ToggleSwitch from '@/components/ui/ToggleSwitch'; - -export default function TableRow({ index, broker, onEdit, onDelete, onToggleStatus, onToggleVisibility, isHidden }) { - const BrokerData = isHidden - ? { name: "---", id: '---', dateAdded: '---', balance: "---" } - : broker; - - return ( - - - {BrokerData.name} - - - {BrokerData.id} - - - - - - {BrokerData.dateAdded} - - - - - - {BrokerData.balance} - - -
- - - -
- - - onToggleStatus(broker.id)} - disabled={isHidden} - /> - - - ); -} diff --git a/src/components/brokers/TableRow.jsx b/src/components/brokers/TableRow.jsx new file mode 100644 index 0000000..7e7734b --- /dev/null +++ b/src/components/brokers/TableRow.jsx @@ -0,0 +1,65 @@ +'use client'; + +import { Edit2, Trash2, LogOut } from 'lucide-react'; +import BrokerAvatar from './BrokerAvatar'; +import StatusIndicator from './StatusIndicator'; +import ToggleSwitch from '@/components/ui/ToggleSwitch'; + +export default function TableRow({ index, broker, onEdit, onDelete, onToggleStatus, onToggleVisibility, isHidden }) { + + return ( + + + {broker.name} + + + {broker.id} + + + + + + {broker.dateAdded} + + + + + + {isHidden?"$-----":broker.balance} + + +
+ + + + +
+ + + onToggleStatus(broker.id)} + /> + + + ); +} diff --git a/src/components/ui/FormInput.js b/src/components/ui/FormInput.jsx similarity index 75% rename from src/components/ui/FormInput.js rename to src/components/ui/FormInput.jsx index 7b75d21..3ef6c8a 100644 --- a/src/components/ui/FormInput.js +++ b/src/components/ui/FormInput.jsx @@ -7,11 +7,12 @@ export default function FormInput({ placeholder, type = "text", required = false, - helperText + helperText , + styleEl='' }) { return (
-