Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .ai/progress.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,35 @@ Each AI run should append an entry with:
* Commit: 3e54e37d98

---

[2026-01-08] Refactor: Refactored betting markets admin components to align with community market design patterns
- Completed GitHub issue #13274
- Key implementation decisions:
* Aligned admin components with MarketsAppPage styling and component patterns (light theme)
* Used CW component kit components (CWText, CWButton, CWTag, CWTextInput, CWSelectList, CWCircleMultiplySpinner)
* Applied light theme styling matching MarketsAppPage: white backgrounds (#ffffff), dark text (#1a1a1a, #212529), light borders (#e9ecef)
* Maintained consistent card styling with hover effects, rounded corners, and gradient provider badges
* Implemented proper empty state handling with descriptive messages
* Used responsive grid layout (2 columns on desktop, 1 on mobile)
* Applied proper status tag color coding (active, new, info)
* Added proper date formatting matching MarketsAppPage patterns
* Replaced inline styles and native HTML elements with CW component kit
- Files changed:
* packages/commonwealth/client/scripts/views/components/MarketIntegrations/MarketSelector.tsx (refactored to use CW components and proper layout)
* packages/commonwealth/client/scripts/views/components/MarketIntegrations/MarketSelector.scss (created new styles matching MarketsAppPage light theme)
* packages/commonwealth/client/scripts/views/components/MarketIntegrations/MarketFilters.tsx (refactored to use CWTextInput and CWSelectList with react-select API)
* packages/commonwealth/client/scripts/views/components/MarketIntegrations/MarketFilters.scss (created responsive filter layout)
* packages/commonwealth/client/scripts/views/components/MarketIntegrations/MarketCard.tsx (refactored to match MarketsAppPage card design with tags, badges, and CWButton)
* packages/commonwealth/client/scripts/views/components/MarketIntegrations/MarketCard.scss (completely rewritten to match MarketsAppPage light theme styling)
* packages/commonwealth/client/scripts/views/components/MarketIntegrations/MarketList.tsx (added proper empty state with CWText)
* packages/commonwealth/client/scripts/views/components/MarketIntegrations/MarketList.scss (updated grid layout and added empty state styles with light theme)
* packages/commonwealth/client/scripts/views/pages/CommunityManagement/Markets/MarketsPage.scss (simplified to match overall structure)
- Tests: All unit tests pass (70 tests in commonwealth package)
- Type checking: No type errors in modified files (pre-existing unrelated errors in model package about Soneium property)
- Linting: All checks pass
- Concerns for reviewers:
* Verify visual consistency between admin and community market views
* Test responsive behavior on mobile devices
* Confirm light theme colors match design system and are consistent
* Validate that status tag colors align with UX expectations
* Check that CWSelectList dropdowns work correctly with react-select API
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,81 +1,94 @@
@use '../../../styles/shared.scss';
@use '../../../styles/mixins/border_radius';
@use '../../../styles/mixins/colors.module';
@use '../../../styles/mixins/elevation';

.market-card {
background: #ffffff;
border-radius: 16px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid #e9ecef;
overflow: hidden;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
// Override default CWCard styles for a darker theme
border: 1px solid colors.$neutral-700; // Subtle dark border
color: colors.$white; // Light text for contrast
padding: 1rem; // Add back padding that was commented out
height: 100%;

&__image-container {
width: calc(100% + 2rem); // Span full width including padding
margin: -1rem -1rem 1rem -1rem; // Adjust margins to align with card edges
height: 120px; // Fixed height for images
overflow: hidden; // Hide overflow for images
border-top-left-radius: border_radius.$border-radius-md;
border-top-right-radius: border_radius.$border-radius-md;

.market-card__image {
width: 100%;
height: 100%;
object-fit: cover; // Cover the container while maintaining aspect ratio
}
&:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
border-color: #dee2e6;
}

&__header {
margin-bottom: 0.75rem; // Increased margin for spacing
padding-bottom: 0.75rem;
border-bottom: 1px solid colors.$neutral-700; // Darker subtle separator

.CWText {
color: colors.$white; // Ensure title is white
font-size: 1.1rem; // Slightly larger for prominence
}
.market-card-content {
padding: 24px;
display: flex;
flex-direction: column;
height: 100%;
gap: 20px;
}

&__body {
flex-grow: 1;
margin-bottom: 1rem; // Increased margin
font-size: 0.85rem; // Slightly smaller details
color: colors.$neutral-300; // Lighter grey for details
.market-card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 12px;
margin-bottom: 4px;

.CWText {
margin-bottom: 0.4rem; // Spacing between details
color: colors.$neutral-300; // Ensure detail text is light grey
}
}
.market-tags {
display: flex;
gap: 8px;
flex-wrap: wrap;
flex: 1;

&__footer {
margin-top: auto;
padding-top: 1rem; // Increased padding
border-top: 1px solid colors.$neutral-700; // Darker subtle separator
.category-tag {
font-size: 12px;
font-weight: 600;
padding: 4px 12px;
border-radius: 6px;
}

button {
width: 100%;
padding: 0.75rem; // More padding for larger button
border-radius: border_radius.$border-radius-md;
border: none; // Remove border, use background color
background-color: colors.$primary-500;
color: colors.$white;
cursor: pointer;
font-weight: 600;
font-size: 0.95rem; // Slightly larger text
.status-tag {
font-size: 11px;
font-weight: 700;
padding: 4px 10px;
border-radius: 6px;
text-transform: uppercase;
letter-spacing: 0.5px;
}

&:hover {
background-color: colors.$primary-600;
.date-tag {
font-size: 11px;
font-weight: 500;
padding: 4px 10px;
border-radius: 6px;
}
}

&:disabled {
background-color: colors.$neutral-700; // Darker disabled background
color: colors.$neutral-500; // Muted disabled text
cursor: not-allowed;
.market-provider {
.provider-badge {
display: inline-block;
padding: 6px 12px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
border-radius: 8px;
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
box-shadow: 0 2px 4px rgba(102, 126, 234, 0.3);
}
}
}

.market-question {
h5 {
color: #212529;
line-height: 1.5;
font-size: 18px;
margin: 0;
}
}

.market-card-footer {
margin-top: auto;
padding-top: 16px;
border-top: 1px solid #e9ecef;
display: flex;
justify-content: flex-end;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from 'react';

import { CWCard } from 'views/components/component_kit/cw_card';
import { CWText } from 'views/components/component_kit/cw_text';

import { CWButton } from 'views/components/component_kit/new_designs/CWButton';
import { CWTag } from 'views/components/component_kit/new_designs/CWTag';
import './MarketCard.scss';
import { Market } from './types';

Expand All @@ -27,38 +26,74 @@ export const MarketCard = ({
}
};

const getStatusTagType = (status: string): 'active' | 'new' | 'info' => {
switch (status) {
case 'open':
return 'active';
case 'closed':
return 'new';
case 'settled':
return 'info';
default:
return 'info';
}
};

const formatDate = (date: Date | null) => {
if (!date) return 'N/A';
const dateObj = typeof date === 'string' ? new Date(date) : date;
return new Intl.DateTimeFormat('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
}).format(dateObj);
};

return (
<CWCard className="market-card" elevation="elevation-1" interactive>
{market.imageUrl && (
<div className="market-card__image-container">
<img
src={market.imageUrl}
alt={market.question}
className="market-card__image"
/>
<div className="market-card">
<div className="market-card-content">
<div className="market-card-header">
<div className="market-tags">
<CWTag
type="info"
label={market.category}
classNames="category-tag"
/>
<CWTag
type={getStatusTagType(market.status)}
label={market.status.toUpperCase()}
classNames="status-tag"
/>
</div>
<div className="market-provider">
<span className="provider-badge">{market.provider}</span>
</div>
</div>
)}
<div className="market-card__header">
<CWText color="white" fontWeight="semiBold">
{market.question}
</CWText>
</div>
<div className="market-card__body">
<CWText>Provider: {market.provider}</CWText>
<CWText>Category: {market.category}</CWText>
</div>
<div className="market-card__footer">
{isSubscribed ? (
<button
style={{ backgroundColor: 'red' }}
onClick={handleToggleSubscription}
>
Unsubscribe
</button>
) : (
<button onClick={handleToggleSubscription}>Subscribe</button>

<div className="market-question">
<CWText fontWeight="semiBold" type="h5">
{market.question}
</CWText>
</div>

{market.startTime && market.endTime && (
<div className="market-date-chip">
<CWTag
type="info"
label={`From ${formatDate(market.startTime)} to ${formatDate(market.endTime)}`}
classNames="date-tag"
/>
</div>
)}

<div className="market-card-footer">
<CWButton
label={isSubscribed ? 'Unsubscribe' : 'Subscribe'}
onClick={handleToggleSubscription}
buttonType={isSubscribed ? 'destructive' : 'primary'}
/>
</div>
</div>
</CWCard>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@use '../../../styles/mixins/media_queries';

.MarketFilters {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 24px;

.filter-search {
width: 100%;
}

.filter-selects {
display: flex;
gap: 16px;

@include media_queries.smallInclusive {
flex-direction: column;
}

> * {
flex: 1;
min-width: 0;
}
}
}
Loading
Loading