Skip to content
Open
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
101 changes: 101 additions & 0 deletions src/components/players/BestMatchCTA.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import React from "react";

interface BestMatchCTAProps {
onClick: () => void;
isMobile: boolean;
}

const BestMatchCTA: React.FC<BestMatchCTAProps> = ({ onClick, isMobile }) => {
return (
<div
style={{
display: "flex",
flexDirection: isMobile ? "column" : "row",
alignItems: isMobile ? "stretch" : "center",
justifyContent: "space-between",
gap: "20px",
padding: isMobile ? "16px" : "20px 24px",
background: "linear-gradient(135deg, #7C3AED 0%, #9333EA 100%)",
borderRadius: "12px",
boxShadow: "0 4px 20px rgba(124, 58, 237, 0.3)",
}}
>
<div
style={{
display: "flex",
alignItems: "center",
gap: "16px",
marginBottom: isMobile ? "14px" : "0",
}}
>
<div
style={{
width: isMobile ? "40px" : "48px",
height: isMobile ? "40px" : "48px",
borderRadius: "12px",
backgroundColor: "rgba(255, 255, 255, 0.2)",
display: "flex",
alignItems: "center",
justifyContent: "center",
flexShrink: 0,
}}
>
<svg width={isMobile ? "20" : "24"} height={isMobile ? "20" : "24"} viewBox="0 0 24 24" fill="none">
<path d="M12 2L14.944 8.062L21.656 9.018L16.828 13.698L17.888 20.382L12 17.262L6.112 20.382L7.172 13.698L2.344 9.018L9.056 8.062L12 2Z" fill="white" />
</svg>
</div>

<div>
<h4
style={{
margin: 0,
fontSize: isMobile ? "16px" : "18px",
fontWeight: 700,
color: "white",
}}
>
Find your perfect tennis partner
</h4>
<p
style={{
margin: "2px 0 0 0",
fontSize: isMobile ? "13px" : "14px",
color: "rgba(255, 255, 255, 0.85)",
}}
>
We'll match you based on skill, availability & location
</p>
</div>
</div>

<button
onClick={onClick}
style={{
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
padding: isMobile ? "14px 20px" : "14px 24px",
backgroundColor: "white",
color: "#7C3AED",
fontSize: "15px",
fontWeight: 600,
borderRadius: "10px",
border: "none",
cursor: "pointer",
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
width: isMobile ? "100%" : "auto",
}}
>
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" style={{ marginRight: 8 }}>
<path d="M9 1L11.472 6.008L17 6.808L13 10.698L13.944 16.2L9 13.608L4.056 16.2L5 10.698L1 6.808L6.528 6.008L9 1Z" fill="currentColor" />
</svg>
Find my best match
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" style={{ marginLeft: 8 }}>
<path d="M6 4L10 8L6 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</button>
</div>
);
};

export default BestMatchCTA;
289 changes: 289 additions & 0 deletions src/components/players/BestMatchCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
import React from "react";

interface Player {
id?: string;
name: string;
photo?: string;
avatarUrl?: string;
ntrp: string;
isVerified?: boolean;
court?: string;
courts?: string[];
matchScore: number;
matchReasons: string[];
}

interface BestMatchCardProps {
player: Player;
onConnect: () => void;
onViewProfile: () => void;
isMobile: boolean;
}

const BestMatchCard: React.FC<BestMatchCardProps> = ({
player,
onConnect,
onViewProfile,
isMobile,
}) => {
return (
<div
style={{
display: "flex",
flexDirection: isMobile ? "column" : "row",
alignItems: isMobile ? "stretch" : "center",
gap: "14px",
padding: isMobile ? "16px 14px 14px" : "14px 16px",
paddingTop: isMobile ? "20px" : "14px",
backgroundColor: "#FAFAFA",
borderRadius: "10px",
border: "1px solid #E5E7EB",
position: "relative",
}}
>
<div
style={{
position: "absolute",
top: "-8px",
left: "16px",
display: "flex",
alignItems: "baseline",
gap: "2px",
padding: "4px 10px",
background: "linear-gradient(135deg, #7C3AED 0%, #9333EA 100%)",
borderRadius: "12px",
boxShadow: "0 2px 6px rgba(124, 58, 237, 0.3)",
}}
>
<span style={{ fontSize: "13px", fontWeight: 700, color: "white" }}>{player.matchScore}%</span>
<span style={{ fontSize: "10px", color: "rgba(255,255,255,0.8)" }}>match</span>
</div>

{isMobile ? (
<>
<div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
<img
src={player.photo || player.avatarUrl}
alt={player.name}
style={{
width: "48px",
height: "48px",
borderRadius: "50%",
objectFit: "cover",
border: "2px solid white",
boxShadow: "0 2px 6px rgba(0,0,0,0.1)",
}}
/>
<div style={{ flex: 1 }}>
<div style={{ display: "flex", alignItems: "center", gap: "8px", marginBottom: "4px" }}>
<span style={{ fontSize: "15px", fontWeight: 600, color: "#111827" }}>{player.name}</span>
<span
style={{
fontSize: "11px",
fontWeight: 500,
color: "white",
backgroundColor: "#7C3AED",
padding: "2px 8px",
borderRadius: "12px",
}}
>
NTRP {player.ntrp}
</span>
{player.isVerified && (
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
<circle cx="7" cy="7" r="6" fill="#ECFDF5" stroke="#A7F3D0" />
<path d="M10 5L6 9L4 7" stroke="#059669" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
)}
</div>
<div style={{ display: "flex", alignItems: "center", fontSize: "12px", color: "#6B7280" }}>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" style={{ marginRight: 4 }}>
<path
d="M6 1C3.79 1 2 2.79 2 5C2 7.75 6 11 6 11C6 11 10 7.75 10 5C10 2.79 8.21 1 6 1Z"
stroke="#9CA3AF"
strokeWidth="1.2"
/>
<circle cx="6" cy="5" r="1.5" stroke="#9CA3AF" strokeWidth="1.2" />
</svg>
{player.court || player.courts?.[0]}
</div>
</div>
</div>

<div style={{ display: "flex", flexWrap: "wrap", gap: "6px", margin: "12px 0" }}>
{player.matchReasons?.map((reason, ridx) => (
<span
key={ridx}
style={{
display: "inline-flex",
alignItems: "center",
fontSize: "11px",
color: "#059669",
backgroundColor: "#ECFDF5",
padding: "3px 8px",
borderRadius: "10px",
border: "1px solid #A7F3D0",
}}
>
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" style={{ marginRight: 4 }}>
<path d="M8 3L4 7L2 5" stroke="#059669" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
{reason}
</span>
))}
</div>

<div style={{ display: "flex", gap: "10px" }}>
<button
onClick={onConnect}
style={{
flex: 1,
padding: "8px 16px",
backgroundColor: "#7C3AED",
color: "white",
fontSize: "13px",
fontWeight: 500,
borderRadius: "6px",
border: "none",
cursor: "pointer",
}}
>
Connect
</button>
<button
onClick={onViewProfile}
style={{
flex: 1,
padding: "8px 16px",
backgroundColor: "white",
color: "#374151",
fontSize: "13px",
fontWeight: 500,
borderRadius: "6px",
border: "1px solid #E5E7EB",
cursor: "pointer",
}}
>
View
</button>
</div>
</>
) : (
<>
<img
src={player.photo || player.avatarUrl}
alt={player.name}
style={{
width: "52px",
height: "52px",
borderRadius: "50%",
objectFit: "cover",
border: "2px solid white",
boxShadow: "0 2px 6px rgba(0,0,0,0.1)",
}}
/>

<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ display: "flex", alignItems: "center", gap: "8px", marginBottom: "6px" }}>
<span style={{ fontSize: "15px", fontWeight: 600, color: "#111827" }}>{player.name}</span>
<span
style={{
fontSize: "11px",
fontWeight: 500,
color: "white",
backgroundColor: "#7C3AED",
padding: "2px 8px",
borderRadius: "12px",
}}
>
NTRP {player.ntrp}
</span>
{player.isVerified && (
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
<circle cx="7" cy="7" r="6" fill="#ECFDF5" stroke="#A7F3D0" />
<path d="M10 5L6 9L4 7" stroke="#059669" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
)}
</div>

<div style={{ display: "flex", flexWrap: "wrap", gap: "6px", marginBottom: "6px" }}>
{player.matchReasons?.map((reason, ridx) => (
<span
key={ridx}
style={{
display: "inline-flex",
alignItems: "center",
fontSize: "11px",
color: "#059669",
backgroundColor: "#ECFDF5",
padding: "3px 8px",
borderRadius: "10px",
border: "1px solid #A7F3D0",
}}
>
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" style={{ marginRight: 4 }}>
<path
d="M8 3L4 7L2 5"
stroke="#059669"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
{reason}
</span>
))}
</div>

<div style={{ display: "flex", alignItems: "center", fontSize: "12px", color: "#6B7280" }}>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" style={{ marginRight: 4 }}>
<path
d="M6 1C3.79 1 2 2.79 2 5C2 7.75 6 11 6 11C6 11 10 7.75 10 5C10 2.79 8.21 1 6 1Z"
stroke="#9CA3AF"
strokeWidth="1.2"
/>
<circle cx="6" cy="5" r="1.5" stroke="#9CA3AF" strokeWidth="1.2" />
</svg>
{player.court || player.courts?.[0]}
</div>
</div>

<div style={{ display: "flex", flexDirection: "column", gap: "6px" }}>
<button
onClick={onConnect}
style={{
padding: "8px 16px",
backgroundColor: "#7C3AED",
color: "white",
fontSize: "13px",
fontWeight: 500,
borderRadius: "6px",
border: "none",
cursor: "pointer",
}}
>
Connect
</button>
<button
onClick={onViewProfile}
style={{
padding: "8px 16px",
backgroundColor: "white",
color: "#374151",
fontSize: "13px",
fontWeight: 500,
borderRadius: "6px",
border: "1px solid #E5E7EB",
cursor: "pointer",
}}
>
View
</button>
</div>
</>
)}
</div>
);
};

export default BestMatchCard;
Loading