Skip to content

Commit 6ec2067

Browse files
authored
Merge pull request #86 from bsychen/fix/product-info-style
Fix/product info style
2 parents 952837a + 94d0870 commit 6ec2067

File tree

10 files changed

+991
-577
lines changed

10 files changed

+991
-577
lines changed

src/components/DislikeButton.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@ export default function DislikeButton({
3232
disabled ? 'cursor-not-allowed opacity-50' : ''
3333
}`}
3434
style={{
35-
backgroundColor: '#f1f5fb',
36-
color: isDisliked ? colours.status.error.text : colours.text.primary
35+
backgroundColor: isDisliked ? `${colours.status.error.background}60`: colours.button.primary.background,
36+
borderColor: isDisliked ? colours.status.error.border : colours.button.primary.text,
37+
color: isDisliked ? colours.status.error.border : colours.button.primary.text
3738
}}
3839
>
39-
<ThumbsDown size={iconSize} className={isDisliked ? 'fill-current' : ''} />
40-
<span>{dislikeCount}</span>
40+
<ThumbsDown size={iconSize} />
41+
<span>{dislikeCount}</span>
4142
</button>
4243
);
4344
}

src/components/LikeButton.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ export default function LikeButton({
3232
disabled ? 'cursor-not-allowed opacity-50' : ''
3333
}`}
3434
style={{
35-
backgroundColor: '#f1f5fb',
36-
color: isLiked ? colours.status.success.text : colours.text.primary
35+
backgroundColor: isLiked ? `${colours.status.success.border}60`: colours.button.primary.background,
36+
color: colours.button.primary.text
3737
}}
3838
>
39-
<ThumbsUp size={iconSize} className={isLiked ? 'fill-current' : ''} />
39+
<ThumbsUp size={iconSize}/>
4040
<span>{likeCount}</span>
4141
</button>
4242
);

src/components/TabbedInfoBox.tsx

Lines changed: 62 additions & 569 deletions
Large diffs are not rendered by default.
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import React from "react";
2+
import { Product } from "@/types/product";
3+
import { colours } from "@/styles/colours";
4+
5+
interface BrandStats {
6+
price: number;
7+
quality: number;
8+
nutrition: number;
9+
sustainability: number;
10+
overallScore: number;
11+
productCount: number;
12+
}
13+
14+
interface BrandTabContentProps {
15+
product: Product;
16+
animatedBrand: number;
17+
calculateBrandStats: BrandStats | null;
18+
}
19+
20+
const BrandTabContent: React.FC<BrandTabContentProps> = ({
21+
animatedBrand,
22+
calculateBrandStats,
23+
}) => {
24+
return (
25+
<div className="w-full flex flex-col items-center opacity-0 animate-fade-in px-1" style={{ animationDelay: '0.05s' }}>
26+
<h2
27+
className="text-lg font-bold mb-2 self-start"
28+
style={{ color: colours.text.primary }}
29+
>
30+
Brand Performance
31+
</h2>
32+
{/* Brand Score Card */}
33+
<div
34+
className="w-full p-3 sm:p-4 rounded-xl border-2 mb-4"
35+
style={{
36+
backgroundColor: '#f1f5fb', // baby blue
37+
borderColor: colours.content.border
38+
}}
39+
>
40+
<div className="flex items-center justify-between gap-3">
41+
<div className="flex flex-col flex-1 min-w-0">
42+
<span
43+
className="text-lg font-medium"
44+
style={{ color: colours.text.primary }}
45+
>
46+
Brand Score
47+
</span>
48+
<span
49+
className="text-[10px]"
50+
style={{ color: colours.text.muted }}
51+
>
52+
Overall brand performance rating
53+
</span>
54+
</div>
55+
<div className="flex-shrink-0">
56+
<div
57+
className="relative w-16 h-16 rounded-full border-2 border-dashed flex items-center justify-center"
58+
style={{
59+
borderColor: (() => {
60+
const score = animatedBrand;
61+
if (score <= 2) return colours.score.low;
62+
if (score <= 3) return colours.score.medium;
63+
return colours.score.high;
64+
})(),
65+
backgroundColor: (() => {
66+
const score = animatedBrand;
67+
if (score <= 2) return colours.score.low + '20'; // 20% opacity
68+
if (score <= 3) return colours.score.medium + '20';
69+
return colours.score.high + '20';
70+
})(),
71+
}}
72+
>
73+
<span className="relative inline-block w-12 h-12 align-middle">
74+
<svg width="48" height="48" viewBox="0 0 48 48" className="absolute top-0 left-0" style={{ zIndex: 1 }}>
75+
<circle
76+
cx="24" cy="24" r="18"
77+
fill="none"
78+
stroke={(() => {
79+
const score = animatedBrand;
80+
if (score <= 2) return colours.score.low;
81+
if (score <= 3) return colours.score.medium;
82+
return colours.score.high;
83+
})()}
84+
strokeWidth="3"
85+
strokeDasharray={Math.PI * 2 * 18}
86+
strokeDashoffset={Math.PI * 2 * 18 * (1 - (animatedBrand / 5))}
87+
strokeLinecap="round"
88+
style={{
89+
transition: 'stroke-dashoffset 0.7s cubic-bezier(0.4,0,0.2,1), stroke 0.7s cubic-bezier(0.4,0,0.2,1)',
90+
transform: 'rotate(-90deg)',
91+
transformOrigin: 'center center',
92+
}}
93+
/>
94+
</svg>
95+
<div className="absolute inset-0 flex flex-col items-center justify-center">
96+
<span
97+
className="text-xl font-bold"
98+
style={{
99+
color: (() => {
100+
const score = animatedBrand;
101+
if (score <= 2) return colours.score.low;
102+
if (score <= 3) return colours.score.medium;
103+
return colours.score.high;
104+
})()
105+
}}
106+
>
107+
{animatedBrand}
108+
</span>
109+
</div>
110+
</span>
111+
</div>
112+
</div>
113+
</div>
114+
</div>
115+
116+
{/* Brand Performance Card */}
117+
<div
118+
className="w-full p-3 sm:p-4 rounded-xl border-2"
119+
style={{
120+
backgroundColor: '#f1f5fb', // baby blue
121+
borderColor: colours.content.border
122+
}}
123+
>
124+
<div className="w-full min-w-0">
125+
<div className="flex items-baseline gap-2 mb-3">
126+
<span
127+
className="text-lg font-medium"
128+
style={{ color: colours.text.primary }}
129+
>
130+
Performance Metrics
131+
</span>
132+
</div>
133+
{calculateBrandStats ? (
134+
<div className="w-full">
135+
<div className="space-y-3">
136+
{[
137+
{ label: 'Price', value: calculateBrandStats.price, color: '#ECCC36' },
138+
{ label: 'Quality', value: calculateBrandStats.quality, color: '#D24330' },
139+
{ label: 'Nutrition', value: calculateBrandStats.nutrition, color: '#3b82f6' },
140+
{ label: 'Sustainability', value: calculateBrandStats.sustainability, color: '#309563' }
141+
].map((stat, index) => (
142+
<div key={stat.label} className="flex items-center gap-3">
143+
<span
144+
className="text-xs font-medium w-20 text-right"
145+
style={{ color: colours.text.secondary }}
146+
>
147+
{stat.label}
148+
</span>
149+
<div className="flex-1 max-w-24">
150+
<div
151+
className="flex items-center h-4 rounded-full overflow-hidden"
152+
style={{ backgroundColor: colours.content.surfaceSecondary }}
153+
>
154+
<div
155+
className="h-full rounded-full transition-all duration-1000 ease-out opacity-0 animate-fade-in"
156+
style={{
157+
width: `${(stat.value / 5) * 100}%`,
158+
backgroundColor: stat.color,
159+
animationDelay: `${0.3 + index * 0.1}s`
160+
}}
161+
/>
162+
</div>
163+
</div>
164+
<span
165+
className="text-xs font-medium w-8"
166+
style={{ color: colours.text.primary }}
167+
>
168+
{stat.value.toFixed(1)}
169+
</span>
170+
</div>
171+
))}
172+
</div>
173+
<div
174+
className="text-xs mt-3 text-center"
175+
style={{ color: colours.text.secondary }}
176+
>
177+
Based on {calculateBrandStats.productCount} products
178+
</div>
179+
</div>
180+
) : (
181+
<div
182+
className="text-sm text-center py-4"
183+
style={{ color: colours.text.secondary }}
184+
>
185+
Not enough brand data available
186+
</div>
187+
)}
188+
</div>
189+
</div>
190+
</div>
191+
);
192+
};
193+
194+
export default BrandTabContent;

0 commit comments

Comments
 (0)