-
Notifications
You must be signed in to change notification settings - Fork 13
PRO-3185-Gas Tank Paymaster #388
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: staging
Are you sure you want to change the base?
Changes from 1 commit
77c38f9
e03e1d9
3b948a8
614d3f9
379171b
0f9902e
7b267f8
fdbb3ba
c22f7b3
271b010
b5bb0b6
2f5d00a
4802b57
28a3d31
18cc95a
ea18ab8
40f84ce
c86ae71
8844e0e
b476b64
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /* eslint-disable @typescript-eslint/no-use-before-define */ | ||
| import styled from 'styled-components'; | ||
|
|
||
| // components | ||
| import UniversalGasTank from './UniversalGasTank'; | ||
| import GasTankHistory from './GasTankHistory'; | ||
|
|
||
| const GasTank = () => { | ||
| return ( | ||
| <Container> | ||
| <LeftSection> | ||
| <UniversalGasTank /> | ||
| </LeftSection> | ||
| <RightSection> | ||
| <GasTankHistory /> | ||
| </RightSection> | ||
| </Container> | ||
| ); | ||
| }; | ||
|
|
||
| const Container = styled.div` | ||
| display: flex; | ||
| gap: 40px; | ||
| max-width: 1200px; | ||
| margin: 0 auto; | ||
| padding: 32px; | ||
|
|
||
| @media (max-width: 768px) { | ||
| flex-direction: column; | ||
| gap: 24px; | ||
| padding: 16px; | ||
| } | ||
| `; | ||
|
|
||
| const LeftSection = styled.div` | ||
| flex: 1; | ||
| max-width: 400px; | ||
|
|
||
| @media (max-width: 768px) { | ||
| max-width: 100%; | ||
| } | ||
| `; | ||
|
|
||
| const RightSection = styled.div` | ||
| flex: 2; | ||
| min-width: 0; | ||
| `; | ||
|
|
||
| export default GasTank; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,233 @@ | ||
| /* eslint-disable @typescript-eslint/no-use-before-define */ | ||
| import { useState } from 'react'; | ||
| import styled from 'styled-components'; | ||
|
|
||
| interface HistoryEntry { | ||
| id: string; | ||
| date: string; | ||
| type: 'Top-up' | 'Spend'; | ||
| amount: string; | ||
| token: { | ||
| symbol: string; | ||
| value: string; | ||
| icon: string; | ||
| }; | ||
| } | ||
|
|
||
| const GasTankHistory = () => { | ||
| const [historyData] = useState<HistoryEntry[]>([ | ||
| { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this supposed to be live data?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah so I am building that data from indexer my work is done there now building a api on x-firebase to get this array |
||
| id: '1', | ||
| date: 'Apr 28, 11:20', | ||
| type: 'Top-up', | ||
| amount: '+$50.00', | ||
| token: { symbol: 'ETH', value: '0.0167', icon: '🔵' }, | ||
| }, | ||
| { | ||
| id: '2', | ||
| date: 'Apr 27, 16:45', | ||
| type: 'Spend', | ||
| amount: '-$2.30 (gas)', | ||
| token: { symbol: 'USDC', value: '2.30', icon: '🔵' }, | ||
| }, | ||
| { | ||
| id: '3', | ||
| date: 'Apr 27, 16:03', | ||
| type: 'Top-up', | ||
| amount: '-$110 (gas)', | ||
| token: { symbol: 'USDC', value: '119', icon: '🔵' }, | ||
| }, | ||
| { | ||
| id: '4', | ||
| date: 'Apr 27, 16:45', | ||
| type: 'Spend', | ||
| amount: '+$47.50', | ||
| token: { symbol: 'OP', value: '30.84', icon: '🔴' }, | ||
| }, | ||
| { | ||
| id: '5', | ||
| date: 'Apr 27, 16:03', | ||
| type: 'Top-up', | ||
| amount: '+$65.00', | ||
| token: { symbol: 'ETH', value: '0.0217', icon: '🔵' }, | ||
| }, | ||
| { | ||
| id: '6', | ||
| date: 'Apr 26, 15:14', | ||
| type: 'Spend', | ||
| amount: '-$3.10 (gas)', | ||
| token: { symbol: 'USDC', value: '3.10', icon: '🔵' }, | ||
| }, | ||
| { | ||
| id: '7', | ||
| date: 'Apr 26, 15:01', | ||
| type: 'Top-up', | ||
| amount: '+$75.00', | ||
| token: { symbol: 'BNB', value: '0.0250', icon: '🟡' }, | ||
| }, | ||
| { | ||
| id: '8', | ||
| date: 'Apr 25, 14:22', | ||
| type: 'Spend', | ||
| amount: '-$5.00 (gas)', | ||
| token: { symbol: 'USDC', value: '5.00', icon: '🔵' }, | ||
| }, | ||
| ]); | ||
|
|
||
| const sortedHistory = historyData.sort( | ||
| (a, b) => new Date(b.date).getTime() - new Date(a.date).getTime() | ||
| ); | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| return ( | ||
| <Container> | ||
| <Header> | ||
| <Icon>📋</Icon> | ||
| <Title>Gas Tank History</Title> | ||
| </Header> | ||
|
|
||
| <Table> | ||
| <TableHeader> | ||
| <HeaderCell>Date ▲</HeaderCell> | ||
| <HeaderCell>Type ▼</HeaderCell> | ||
| <HeaderCell>Amount ▼</HeaderCell> | ||
| <HeaderCell>Token ▼</HeaderCell> | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remember to check the AI Agent output as the column sort buttons are text character arrows here but should sort
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah one thing at a time I saw it and thought I will change this to sorted once I get all the data
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm assuming the same as previously mentioned - this is supposed to be sortable |
||
| </TableHeader> | ||
|
|
||
| <TableBody> | ||
| {sortedHistory.map((entry) => ( | ||
| <TableRow key={entry.id}> | ||
| <DateCell>{entry.date}</DateCell> | ||
| <TypeCell>{entry.type}</TypeCell> | ||
| <AmountCell isPositive={entry.amount.startsWith('+')}> | ||
| {entry.amount} | ||
| </AmountCell> | ||
| <TokenCell> | ||
| <TokenIcon>{entry.token.icon}</TokenIcon> | ||
| <TokenInfo> | ||
| <TokenValue>{entry.token.value}</TokenValue> | ||
| <TokenSymbol>{entry.token.symbol}</TokenSymbol> | ||
| </TokenInfo> | ||
| </TokenCell> | ||
| </TableRow> | ||
| ))} | ||
| </TableBody> | ||
| </Table> | ||
| </Container> | ||
| ); | ||
| }; | ||
|
|
||
| const Container = styled.div` | ||
| background: #1a1a1a; | ||
| border-radius: 16px; | ||
| padding: 24px; | ||
| border: 1px solid #333; | ||
| `; | ||
|
|
||
| const Header = styled.div` | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 8px; | ||
| margin-bottom: 24px; | ||
| `; | ||
|
|
||
| const Icon = styled.span` | ||
| font-size: 18px; | ||
| `; | ||
|
|
||
| const Title = styled.h2` | ||
| color: #ffffff; | ||
| font-size: 18px; | ||
| font-weight: 600; | ||
| margin: 0; | ||
| `; | ||
|
|
||
| const Table = styled.div` | ||
| width: 100%; | ||
| `; | ||
|
|
||
| const TableHeader = styled.div` | ||
| display: grid; | ||
| grid-template-columns: 1fr 1fr 1fr 1fr; | ||
| gap: 16px; | ||
| padding-bottom: 12px; | ||
| border-bottom: 1px solid #333; | ||
| margin-bottom: 8px; | ||
| `; | ||
|
|
||
| const HeaderCell = styled.div` | ||
| color: #9ca3af; | ||
| font-size: 12px; | ||
| font-weight: 500; | ||
| text-transform: uppercase; | ||
| letter-spacing: 0.5px; | ||
| `; | ||
|
|
||
| const TableBody = styled.div` | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: 8px; | ||
| `; | ||
|
|
||
| const TableRow = styled.div` | ||
| display: grid; | ||
| grid-template-columns: 1fr 1fr 1fr 1fr; | ||
| gap: 16px; | ||
| padding: 12px 0; | ||
| border-bottom: 1px solid #2a2a2a; | ||
| align-items: center; | ||
|
|
||
| &:last-child { | ||
| border-bottom: none; | ||
| } | ||
| `; | ||
|
|
||
| const DateCell = styled.div` | ||
| color: #ffffff; | ||
| font-size: 14px; | ||
| `; | ||
|
|
||
| const TypeCell = styled.div` | ||
| color: #ffffff; | ||
| font-size: 14px; | ||
| `; | ||
|
|
||
| const AmountCell = styled.div<{ isPositive: boolean }>` | ||
| color: ${(props) => (props.isPositive ? '#4ade80' : '#ef4444')}; | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| `; | ||
|
|
||
| const TokenCell = styled.div` | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 8px; | ||
| `; | ||
|
|
||
| const TokenIcon = styled.span` | ||
| width: 20px; | ||
| height: 20px; | ||
| border-radius: 50%; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| font-size: 12px; | ||
| `; | ||
|
|
||
| const TokenInfo = styled.div` | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 4px; | ||
| `; | ||
|
|
||
| const TokenValue = styled.span` | ||
| color: #ffffff; | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| `; | ||
|
|
||
| const TokenSymbol = styled.span` | ||
| color: #9ca3af; | ||
| font-size: 12px; | ||
| `; | ||
|
|
||
| export default GasTankHistory; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Sort by a stable numeric timestamp, not a formatted date string.
Parsing localized strings is brittle and can misorder data. Persist the raw timestamp and sort on it.
interface HistoryEntry { id: string; date: string; + timestamp: number; type: 'Top-up' | 'Spend'; amount: string; token: {const entries: HistoryEntry[] = (data.history || []).map((item: any, idx: number) => { const isDeposit = item.transactionType === 'Deposit'; return { id: String(idx + 1), // Numeric id starting from 1 date: formatTimestamp(item.timestamp), + timestamp: Number(item.timestamp), type: isDeposit ? 'Top-up' : 'Spend', amount: formatAmount(item.amount, isDeposit), token: {Also applies to: 62-76, 124-127