نسخ من mohammedsaid18/dashboard
Make like figma and add the showKeywordAnalysis and new card
هذا الالتزام موجود في:
72
src/App.css
72
src/App.css
@@ -3,40 +3,58 @@
|
|||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
/* max-width: 1500px; */
|
/* max-width: 1500px; */
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media (max-width: 1299px) {
|
||||||
|
.container {
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1300px) {
|
||||||
@media (max-width: 1299px) {
|
.container {
|
||||||
.container {
|
max-width: 1300px;
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 1300px) {
|
@media (min-width: 1500px) {
|
||||||
.container {
|
.container {
|
||||||
max-width: 1300px;
|
max-width: 1500px;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 1600px) {
|
@media (min-width: 1600px) {
|
||||||
.container {
|
.container {
|
||||||
max-width: 1600px;
|
max-width: 1600px;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.recharts-surface {
|
.recharts-surface {
|
||||||
cursor: pointer !important;
|
cursor: pointer !important;
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
focus:outline-none !important;
|
focus: outline-none !important;
|
||||||
focus:ring-0 !important;
|
focus: ring-0 !important;
|
||||||
focus:border-none !important;
|
focus: border-none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) and (max-width: 1250px) {
|
||||||
|
.pr-m-5 {
|
||||||
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) and (max-width: 1296px) {
|
||||||
|
.w-m-40 {
|
||||||
|
width: 40% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -95,14 +95,14 @@ const CampaignTracker = ({ handleMenuClick }: { handleMenuClick: () => void }) =
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Progress Sections */}
|
{/* Progress Sections */}
|
||||||
<div className="space-y-6">
|
<div className="space-y-8">
|
||||||
{progressSections.map((section, index) => {
|
{progressSections.map((section, index) => {
|
||||||
const progressPercentage = (section.current / section.total) * 100
|
const progressPercentage = (section.current / section.total) * 100
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={index} className="space-y-1">
|
<div key={index} className="space-y-1">
|
||||||
{/* Section Title and Progress */}
|
{/* Section Title and Progress */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between mb-2">
|
||||||
<h3 className="text-sm font-semibold text-gray-900">
|
<h3 className="text-sm font-semibold text-gray-900">
|
||||||
{section.title}: {section.current}/{section.total}
|
{section.title}: {section.current}/{section.total}
|
||||||
</h3>
|
</h3>
|
||||||
|
|||||||
@@ -9,13 +9,16 @@ import {
|
|||||||
Info,
|
Info,
|
||||||
ArrowUp,
|
ArrowUp,
|
||||||
Link,
|
Link,
|
||||||
ChevronDown
|
ChevronDown,
|
||||||
|
MapPin,
|
||||||
|
Sparkles
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import MetricCard from "./shared/MetricCard";
|
import MetricCard from "./shared/MetricCard";
|
||||||
import UrlDropdown from "./shared/UrlDropdown";
|
import UrlDropdown from "./shared/UrlDropdown";
|
||||||
import HeaderPage from "./shared/HeaderPage";
|
import HeaderPage from "./shared/HeaderPage";
|
||||||
import Google from "../assets/icons/google-original-logo.svg";
|
import Google from "../assets/icons/google-original-logo.svg";
|
||||||
import Gemini from "../assets/icons/gemini.svg";
|
import Gemini from "../assets/icons/gemini.svg";
|
||||||
|
import Gemini2 from "../assets/icons/gemini2.svg";
|
||||||
import Perplexity from "../assets/icons/perplexity-dark-logo.svg";
|
import Perplexity from "../assets/icons/perplexity-dark-logo.svg";
|
||||||
import Vector from "../assets/icons/Vector.png";
|
import Vector from "../assets/icons/Vector.png";
|
||||||
import Vector2 from "../assets/icons/Vector2.png";
|
import Vector2 from "../assets/icons/Vector2.png";
|
||||||
@@ -236,6 +239,103 @@ const CARDS = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const competitors = [
|
||||||
|
{
|
||||||
|
domain: "Cherrybekaertla.com",
|
||||||
|
googleRank: 1,
|
||||||
|
mapPins: 7,
|
||||||
|
hasAi: true,
|
||||||
|
hasCircle: true,
|
||||||
|
hasDiamond: true,
|
||||||
|
hasTree: true,
|
||||||
|
hasLLM: true,
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
content: [
|
||||||
|
{ icon: "Google", value: "1" }
|
||||||
|
],
|
||||||
|
color: "#4285F4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: [
|
||||||
|
{ icon: "Map", value: "7", }
|
||||||
|
],
|
||||||
|
color: "#4285F4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: [
|
||||||
|
{ icon: "Ai" },
|
||||||
|
{ icon: "Perplexity" },
|
||||||
|
{ icon: "GPT" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
domain: "Gerbercompany.com",
|
||||||
|
googleRank: 1,
|
||||||
|
mapPins: 7,
|
||||||
|
hasAi: true,
|
||||||
|
hasCircle: true,
|
||||||
|
hasDiamond: true,
|
||||||
|
hasTree: true,
|
||||||
|
hasLLM: true,
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
content: [
|
||||||
|
{ icon: "Google", value: "1" }
|
||||||
|
],
|
||||||
|
color: "#4285F4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: [
|
||||||
|
{ icon: "Map", value: "7", }
|
||||||
|
],
|
||||||
|
color: "#4285F4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: [
|
||||||
|
{ icon: "Ai" },
|
||||||
|
{ icon: "Perplexity" },
|
||||||
|
{ icon: "GPT" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
domain: "Mysite.com",
|
||||||
|
googleRank: 1,
|
||||||
|
mapPins: 7,
|
||||||
|
hasAi: true,
|
||||||
|
hasCircle: true,
|
||||||
|
hasDiamond: true,
|
||||||
|
hasTree: true,
|
||||||
|
hasLLM: true,
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
content: [
|
||||||
|
{ icon: "Google", value: "1" }
|
||||||
|
],
|
||||||
|
color: "#4285F4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: [
|
||||||
|
{ icon: "Map", value: "7", }
|
||||||
|
],
|
||||||
|
color: "#4285F4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: [
|
||||||
|
{ icon: "Ai" },
|
||||||
|
{ icon: "Perplexity" },
|
||||||
|
{ icon: "GPT" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
const pillClass = (val: string) =>
|
const pillClass = (val: string) =>
|
||||||
val === 'Done' ? 'bg-green-100 text-green-700 font-bold'
|
val === 'Done' ? 'bg-green-100 text-green-700 font-bold'
|
||||||
: val === 'In Progress' ? 'bg-blue-100 text-blue-700 font-bold'
|
: val === 'In Progress' ? 'bg-blue-100 text-blue-700 font-bold'
|
||||||
@@ -247,6 +347,7 @@ export default function DashboardGrid() {
|
|||||||
const [activeCard, setActiveCard] = useState<string | null>(null);
|
const [activeCard, setActiveCard] = useState<string | null>(null);
|
||||||
const [hoverState, setHoverState] = useState<HoverState>({ cardId: null, ringIndex: null });
|
const [hoverState, setHoverState] = useState<HoverState>({ cardId: null, ringIndex: null });
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
|
const [showKeywordAnalysis, setShowKeywordAnalysis] = useState<string | null>(null);
|
||||||
|
|
||||||
const handleCardClick = (campaignName: string, paused: boolean) => {
|
const handleCardClick = (campaignName: string, paused: boolean) => {
|
||||||
if (paused) return;
|
if (paused) return;
|
||||||
@@ -275,6 +376,14 @@ export default function DashboardGrid() {
|
|||||||
setHoverState({ cardId, ringIndex });
|
setHoverState({ cardId, ringIndex });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleResumeClick = (campaignName: string) => {
|
||||||
|
setShowKeywordAnalysis(campaignName);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseKeywordAnalysis = () => {
|
||||||
|
setShowKeywordAnalysis(null);
|
||||||
|
};
|
||||||
|
|
||||||
const TagComponent = ({ content, color = "#4285F4", faded = false }: Tag & { faded?: boolean }) => {
|
const TagComponent = ({ content, color = "#4285F4", faded = false }: Tag & { faded?: boolean }) => {
|
||||||
const getIconContent = (item: TagContent) => {
|
const getIconContent = (item: TagContent) => {
|
||||||
switch (item.icon) {
|
switch (item.icon) {
|
||||||
@@ -282,7 +391,7 @@ export default function DashboardGrid() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<img src={Google} alt="Google" className="w-5 h-5" />
|
<img src={Google} alt="Google" className="w-5 h-5" />
|
||||||
{item.value && <span className="text-black font-bold text-md">{item.value}</span>}
|
{item.value && <span className="text-[#17171B] font-semibold text-md">{item.value}</span>}
|
||||||
{item.extra && (
|
{item.extra && (
|
||||||
<span className={`ml-1 text-md ${item.extra.startsWith('+') ? 'text-green-600' : 'text-red-600'} font-bold`}>
|
<span className={`ml-1 text-md ${item.extra.startsWith('+') ? 'text-green-600' : 'text-red-600'} font-bold`}>
|
||||||
{item.extra}
|
{item.extra}
|
||||||
@@ -293,7 +402,7 @@ export default function DashboardGrid() {
|
|||||||
case "Map":
|
case "Map":
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<img src={Map} alt="Map" className="w-5 h-5" />
|
<img src={Map} alt="Map" className="w-5 h-6" />
|
||||||
{item.value && <span className="text-black font-bold text-md">{item.value}</span>}
|
{item.value && <span className="text-black font-bold text-md">{item.value}</span>}
|
||||||
{item.extra && (
|
{item.extra && (
|
||||||
<span className={`ml-1 text-md ${item.extra.startsWith('+') ? 'text-green-600' : 'text-red-600'} font-bold`}>
|
<span className={`ml-1 text-md ${item.extra.startsWith('+') ? 'text-green-600' : 'text-red-600'} font-bold`}>
|
||||||
@@ -303,11 +412,41 @@ export default function DashboardGrid() {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
case "Ai":
|
case "Ai":
|
||||||
return <img src={Gemini} alt="AI" className="w-5 h-5" />;
|
return (
|
||||||
|
<>
|
||||||
|
<img src={Gemini2} alt="AI" className="w-5 h-5" />
|
||||||
|
{item.value && <span className="text-black font-bold text-md">{item.value}</span>}
|
||||||
|
{item.extra && (
|
||||||
|
<span className={`ml-1 text-md ${item.extra.startsWith('+') ? 'text-green-600' : 'text-red-600'} font-bold`}>
|
||||||
|
{item.extra}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
case "GPT":
|
case "GPT":
|
||||||
return <img src={GPT} alt="GPT" className="w-5 h-5" />;
|
return (
|
||||||
|
<>
|
||||||
|
<img src={GPT} alt="GPT" className="w-5 h-5" />
|
||||||
|
{item.value && <span className="text-black font-bold text-md">{item.value}</span>}
|
||||||
|
{item.extra && (
|
||||||
|
<span className={`ml-1 text-md ${item.extra.startsWith('+') ? 'text-green-600' : 'text-red-600'} font-bold`}>
|
||||||
|
{item.extra}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
case "Perplexity":
|
case "Perplexity":
|
||||||
return <img src={Perplexity} alt="Perplexity" className="w-5 h-5" />;
|
return (
|
||||||
|
<>
|
||||||
|
<img src={Perplexity} alt="Perplexity" className="w-5 h-5" />
|
||||||
|
{item.value && <span className="text-black font-bold text-md">{item.value}</span>}
|
||||||
|
{item.extra && (
|
||||||
|
<span className={`ml-1 text-md ${item.extra.startsWith('+') ? 'text-green-600' : 'text-red-600'} font-bold`}>
|
||||||
|
{item.extra}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
default:
|
default:
|
||||||
return item.text || null;
|
return item.text || null;
|
||||||
}
|
}
|
||||||
@@ -401,59 +540,119 @@ export default function DashboardGrid() {
|
|||||||
<div className={`relative w-full h-full transition-transform duration-700 ease-in-out [transform-style:preserve-3d] ${selectedCampaigns.includes(card.title) ? '[transform:rotateY(180deg)]' : ''
|
<div className={`relative w-full h-full transition-transform duration-700 ease-in-out [transform-style:preserve-3d] ${selectedCampaigns.includes(card.title) ? '[transform:rotateY(180deg)]' : ''
|
||||||
}`}>
|
}`}>
|
||||||
{/* Front of card */}
|
{/* Front of card */}
|
||||||
<div className={`absolute w-full h-full [backface-visibility:hidden] bg-white rounded-2xl shadow-lg border transition-all duration-300 ease-in-out cursor-pointer ${card.faded ? "opacity-60" : ""}
|
<div className={`absolute w-full h-full [backface-visibility:hidden] bg-white rounded-2xl border transition-all duration-300 ease-in-out cursor-pointer ${card.faded ? "opacity- 60" : ""}
|
||||||
${selectedCampaigns.includes(card.title) ? 'shadow-2xl scale-[1.02]' : 'hover:scale-105 hover:shadow-xl'
|
${selectedCampaigns.includes(card.title) ? 'shadow-md scale-[1.02]' : 'hover:scale-135 hover:shadow-md'
|
||||||
}`}
|
}`}
|
||||||
style={{
|
style={{
|
||||||
transform: selectedCampaigns.includes(card.title)
|
transform: selectedCampaigns.includes(card.title)
|
||||||
? 'translateY(-5px) scale(1.02)'
|
? 'translateY(-5px) scale(1.02)'
|
||||||
: 'translateY(0px) scale(1)'
|
: 'translateY(0px) scale(1)'
|
||||||
}}>
|
}}>
|
||||||
<div className="p-5 flex flex-col items-center h-full">
|
{
|
||||||
{card.badge && (
|
card.paused && showKeywordAnalysis === card.title
|
||||||
<div className="absolute top-0 right-0 overflow-hidden w-32 h-32 pointer-events-none">
|
?
|
||||||
<div className="absolute top-6 right-[-100px] w-[320px] bg-[#0CAA75] text-white font-semibold py-4 flex items-center justify-center gap-3 rotate-45 shadow-lg">
|
<div className="bg-[#f6f8fe] rounded-xl shadow-sm border border-gray-200 p-6 px-20 h-full">
|
||||||
<div className="flex items-center justify-center gap-1 text-xs font-bold whitespace-nowrap">
|
{/* New Keyword Badge */}
|
||||||
<svg width="14" height="11" viewBox="0 0 14 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M6.20122 0.94856L9.60703 1.3343C11.8086 1.58456 12.9094 1.70875 13.0543 2.33535C13.1991 2.96195 12.2508 3.50763 10.3588 4.59994L10.18 4.70343C9.4979 5.09764 9.15638 5.29427 9.06888 5.6358L9.06417 5.65367C8.98326 5.99802 9.18836 6.35365 9.59857 7.06304C10.3371 8.34164 10.7069 8.98046 10.4434 9.42077L10.4293 9.44241C10.1527 9.87331 9.43957 9.7924 8.0095 9.63058L4.60462 9.2439C2.40307 8.99552 1.30323 8.87039 1.15834 8.24379C1.01345 7.61719 1.96088 7.07057 3.85289 5.97826L4.03165 5.87477C4.71376 5.48244 5.05434 5.28486 5.14372 4.94334L5.14842 4.92547C5.22839 4.58206 5.02329 4.22643 4.61403 3.5161C3.87547 2.2375 3.50573 1.59868 3.76916 1.15837L3.78327 1.13673C4.058 0.705826 4.77303 0.786737 6.20122 0.94856Z" stroke="white" strokeWidth="1.625" />
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
<span>{card.badge}</span>
|
<div className="flex justify-center mb-4">
|
||||||
|
<div className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-sm font-medium text-[#197232]" style={{ background: "linear-gradient(90deg, #d6fbe2 30%, #edf9d5 100%)" }}>
|
||||||
|
<Sparkles className="w-4 h-4" />
|
||||||
|
NEW High-Value Keyword Found
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Keyword Title */}
|
||||||
|
<h2 className="text-2xl font-bold text-gray-900 text-center mb-6">Tax Prep Attorney Los Angeles</h2>
|
||||||
|
|
||||||
|
{/* Competitors List */}
|
||||||
|
<div className="space-y-4 mb-6">
|
||||||
|
{competitors.map((competitor, index) => (
|
||||||
|
<div key={index} className="space-y-2">
|
||||||
|
<div className="text-md text-gray-600 font-bold">{competitor.domain}</div>
|
||||||
|
<div className="flex items-center gap-3 flex-wrap">
|
||||||
|
{competitor.tags.map((tag, i) => (
|
||||||
|
<TagComponent
|
||||||
|
key={i}
|
||||||
|
{...tag}
|
||||||
|
faded={card.faded}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom CTA */}
|
||||||
|
<div className="text-center">
|
||||||
|
<p className="text-md text-gray-500 ">Your competitors own this keyword.</p>
|
||||||
|
<p className="text-md font-semibold text-[#2B2D3B] mb-3">Add it to capture visibility and sales.</p>
|
||||||
|
<button className="inline-flex items-center gap-2 px-6 py-2 bg-indigo-600 hover:bg-indigo-700 text-white font-medium rounded-lg transition-colors">
|
||||||
|
<span className="text-lg">+</span>
|
||||||
|
Add Keyword
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
:
|
||||||
<MultiRingCircularProgress
|
<div className="p-5 flex flex-col items-center h-full">
|
||||||
card={card}
|
{card.badge && (
|
||||||
hoveredIndex={hoverState.cardId === card.title ? hoverState.ringIndex : null}
|
<div className="absolute top-0 right-0 overflow-hidden w-32 h-32 pointer-events-none">
|
||||||
onHover={(index) => handleRingHover(card.title, index)}
|
<div className="absolute top-6 right-[-100px] w-[320px] bg-[#0CAA75] text-white font-semibold py-4 flex items-center justify-center gap-3 rotate-45 shadow-lg">
|
||||||
cardId={card.title}
|
<div className="flex items-center justify-center gap-1 text-xs font-bold whitespace-nowrap">
|
||||||
/>
|
<svg width="14" height="11" viewBox="0 0 14 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<div className={`mt-1 font-bold text-lg text-center ${card.faded ? "text-gray-400" : "text-gray-900"}`}>
|
<path d="M6.20122 0.94856L9.60703 1.3343C11.8086 1.58456 12.9094 1.70875 13.0543 2.33535C13.1991 2.96195 12.2508 3.50763 10.3588 4.59994L10.18 4.70343C9.4979 5.09764 9.15638 5.29427 9.06888 5.6358L9.06417 5.65367C8.98326 5.99802 9.18836 6.35365 9.59857 7.06304C10.3371 8.34164 10.7069 8.98046 10.4434 9.42077L10.4293 9.44241C10.1527 9.87331 9.43957 9.7924 8.0095 9.63058L4.60462 9.2439C2.40307 8.99552 1.30323 8.87039 1.15834 8.24379C1.01345 7.61719 1.96088 7.07057 3.85289 5.97826L4.03165 5.87477C4.71376 5.48244 5.05434 5.28486 5.14372 4.94334L5.14842 4.92547C5.22839 4.58206 5.02329 4.22643 4.61403 3.5161C3.87547 2.2375 3.50573 1.59868 3.76916 1.15837L3.78327 1.13673C4.058 0.705826 4.77303 0.786737 6.20122 0.94856Z" stroke="white" strokeWidth="1.625" />
|
||||||
{card.title}
|
</svg>
|
||||||
</div>
|
|
||||||
{/* Tags */}
|
<span>{card.badge}</span>
|
||||||
<div className="mt-2 flex flex-row gap-2 flex-wrap justify-center">
|
</div>
|
||||||
{card.tags.map((tag, i) => (
|
</div>
|
||||||
<TagComponent
|
</div>
|
||||||
key={i}
|
)}
|
||||||
{...tag}
|
<MultiRingCircularProgress
|
||||||
faded={card.faded}
|
card={card}
|
||||||
|
hoveredIndex={hoverState.cardId === card.title ? hoverState.ringIndex : null}
|
||||||
|
onHover={(index) => handleRingHover(card.title, index)}
|
||||||
|
cardId={card.title}
|
||||||
/>
|
/>
|
||||||
))}
|
<div className={`mt-1 font-bold text-lg text-center ${card.faded ? "text-gray-400" : "text-gray-900"}`}>
|
||||||
</div>
|
{card.title}
|
||||||
{card.actionLink && (
|
</div>
|
||||||
<div className="mt-3 text-blue-600 text-sm cursor-pointer hover:underline transition-all duration-300 hover:text-blue-800">
|
{/* Tags */}
|
||||||
{card.actionLink}
|
<div className="mt-2 flex flex-row gap-2 flex-wrap justify-center">
|
||||||
|
{card.tags.map((tag, i) => (
|
||||||
|
<TagComponent
|
||||||
|
key={i}
|
||||||
|
{...tag}
|
||||||
|
faded={card.faded}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{card.actionLink && (
|
||||||
|
<div className="mt-3 text-blue-600 text-sm cursor-pointer hover:underline transition-all duration-300 hover:text-blue-800">
|
||||||
|
{card.actionLink}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{card.paused && (
|
||||||
|
<div className="mt-1 text-center">
|
||||||
|
<div className="text-gray-400 text-sm">Campaign paused</div>
|
||||||
|
<button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleResumeClick(card.title);
|
||||||
|
}}
|
||||||
|
className="text-blue-600 text-sm hover:underline transition-all duration-300 hover:text-blue-800"
|
||||||
|
>
|
||||||
|
Resume
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
{card.paused && (
|
}
|
||||||
<div className="mt-1 text-center">
|
|
||||||
<div className="text-gray-400 text-sm">Campaign paused</div>
|
|
||||||
<button className="text-blue-600 text-sm hover:underline transition-all duration-300 hover:text-blue-800">Resume</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Back of card */}
|
{/* Back of card */}
|
||||||
@@ -536,6 +735,7 @@ export default function DashboardGrid() {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ export default function MultiRingCircularProgress({ card, hoveredIndex, onHover,
|
|||||||
onMouseEnter={() => onHover(index)}
|
onMouseEnter={() => onHover(index)}
|
||||||
onMouseLeave={() => onHover(null)}
|
onMouseLeave={() => onHover(null)}
|
||||||
fill={getHoverColor(ring, index)}
|
fill={getHoverColor(ring, index)}
|
||||||
|
className="focus:outline-none focus:ring-0 focus:border-none"
|
||||||
// pointerEvents={'none'}
|
// pointerEvents={'none'}
|
||||||
>
|
>
|
||||||
<Cell
|
<Cell
|
||||||
|
|||||||
@@ -28,13 +28,14 @@ const BacklinkTypeDropdown = ({ options, title, subTitle }: { options: Record<st
|
|||||||
return (
|
return (
|
||||||
<div className='relative' ref={dropdownRef}>
|
<div className='relative' ref={dropdownRef}>
|
||||||
<button
|
<button
|
||||||
className='border rounded-lg px-3 py-1 bg-white text-gray-500 font-medium flex items-center text-md'
|
className={`border rounded-lg px-3 py-1 bg-white text-gray-500 font-medium flex items-center text-md ${dropdownOpen ? "border-2 border-solid border-blue-500" : ""}`}
|
||||||
onClick={() => setDropdownOpen(v => !v)}
|
onClick={() => setDropdownOpen(v => !v)}
|
||||||
>
|
>
|
||||||
{title} <ChevronDown className='ml-2' />
|
{title}
|
||||||
|
<ChevronDown className='ml-2' />
|
||||||
</button>
|
</button>
|
||||||
{dropdownOpen && (
|
{dropdownOpen && (
|
||||||
<div className='absolute z-10 bg-white shadow-lg border rounded-lg top-[110%] right-0 px-4 py-3 min-w-[150px]'>
|
<div className={`absolute z-10 bg-white shadow-lg border rounded-lg top-[110%] right-0 px-4 py-3 min-w-[150px] `}>
|
||||||
<div className='font-semibold text-md text-gray-700 mb-2'>{subTitle}:</div>
|
<div className='font-semibold text-md text-gray-700 mb-2'>{subTitle}:</div>
|
||||||
{Object.keys(checkedRings).map((ring, idx) => (
|
{Object.keys(checkedRings).map((ring, idx) => (
|
||||||
<label
|
<label
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function ProgressMetrics() {
|
|||||||
<div className="w-[100%]">
|
<div className="w-[100%]">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="text-lg 3xl:text-4xl font-bold text-gray-900 mb-1">60%</div>
|
<div className="text-lg 3xl:text-4xl font-bold text-gray-900 mb-1">60%</div>
|
||||||
<div className="text-lg 3xl:text-3xl font-bold text-gray-900 mb-1">120/250 <span className="text-gray-500">links</span></div>
|
<div className="text-md 3xl:text-3xl font-bold text-gray-900 mb-1">120/250 <span className="text-gray-500">links</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs 2xl:text-sm text-gray-500 mb-2">until content publishing + LLM seeding unlocked</div>
|
<div className="text-xs 2xl:text-sm text-gray-500 mb-2">until content publishing + LLM seeding unlocked</div>
|
||||||
{/* Progress bar */}
|
{/* Progress bar */}
|
||||||
@@ -49,7 +49,7 @@ function ProgressMetrics() {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center md:w-1/3 w-full md:border-r-2 border-0 border-solid border-gray-300 2xl:gap-12 lg:gap-6 gap-3">
|
<div className="flex items-center md:w-1/3 w-full md:border-r-2 border-0 border-solid border-gray-300 2xl:gap-12 lg:gap-3 gap-3 pr-m-5 w-m-40">
|
||||||
{/* 75% Keyword Visibility */}
|
{/* 75% Keyword Visibility */}
|
||||||
<div className="w-[30%]">
|
<div className="w-[30%]">
|
||||||
<div className="text-xl 2xl:text-3xl font-bold text-gray-900 mb-1">75%</div>
|
<div className="text-xl 2xl:text-3xl font-bold text-gray-900 mb-1">75%</div>
|
||||||
@@ -57,16 +57,12 @@ function ProgressMetrics() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-3 w-[100%]">
|
<div className="flex items-center gap-3 w-[100%]">
|
||||||
<div className="flex items-center gap-3 flex-wrap">
|
<div className="flex items-center gap-3 ">
|
||||||
<MetricCard
|
<MetricCard
|
||||||
img={Google} tooltipText="Google" valueChange="+1" size="sm" disabled />
|
img={Google} tooltipText="Google" valueChange="+1" size="sm" disabled />
|
||||||
|
|
||||||
<MetricCard
|
<MetricCard
|
||||||
img={Map} tooltipText="Map" valueChange="+1" size="sm" disabled value="Map" />
|
img={Map} tooltipText="Map" valueChange="+1" size="sm" disabled value="Map" />
|
||||||
|
|
||||||
{/* <MetricCard
|
|
||||||
img={Gemini} tooltipText="ChatGPT" valueChange="+1" size="sm" extraStyle="border-2 border-solid border-gray-300 rounded-lg " /> */}
|
|
||||||
|
|
||||||
<MetricCard
|
<MetricCard
|
||||||
img={ChatGPT} tooltipText="ChatGPT" valueChange="+1" size="sm" />
|
img={ChatGPT} tooltipText="ChatGPT" valueChange="+1" size="sm" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,11 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
import Vector from "../assets/icons/Vector.png"
|
|
||||||
import Vector2 from "../assets/icons/Vector2.png"
|
|
||||||
import BacklinkTypeDropdown from '../components/Portfolio/BacklinkTypeDropdown';
|
import BacklinkTypeDropdown from '../components/Portfolio/BacklinkTypeDropdown';
|
||||||
import RoadmapSidebar from '../components/Strategy/RoadmapSidebar';
|
import RoadmapSidebar from '../components/Strategy/RoadmapSidebar';
|
||||||
import HeaderPage from '../components/shared/HeaderPage';
|
import HeaderPage from '../components/shared/HeaderPage';
|
||||||
import ContainerPage from '../components/shared/ContainerPage';
|
import ContainerPage from '../components/shared/ContainerPage';
|
||||||
import Amazing from "../assets/icons/amazon.png"
|
import Amazing from "../assets/icons/amazon.svg"
|
||||||
import { CircleCheck } from 'lucide-react';
|
import { CircleCheck } from 'lucide-react';
|
||||||
// import Pinterest from "../assets/icons/pinterest.png"
|
|
||||||
// import AppleMusic from "../assets/icons/apple-music.png"
|
|
||||||
// import Substack from "../assets/icons/substack.png"
|
|
||||||
// import Pin from "../assets/icons/pin.png"
|
|
||||||
import Progress from "../assets/icons/InProgress.svg"
|
import Progress from "../assets/icons/InProgress.svg"
|
||||||
import No from "../assets/icons/NA.svg"
|
import No from "../assets/icons/NA.svg"
|
||||||
import Share2 from "../assets/icons/Share2.png"
|
import Share2 from "../assets/icons/Share2.png"
|
||||||
@@ -108,7 +102,7 @@ function Portfolio() {
|
|||||||
|
|
||||||
<BacklinkTypeDropdown options={{ DA: true, DR: true, Traffic: true }} title="Traffic" subTitle="Show rings:" />
|
<BacklinkTypeDropdown options={{ DA: true, DR: true, Traffic: true }} title="Traffic" subTitle="Show rings:" />
|
||||||
|
|
||||||
<button className='bg-[#fff] text-gray-500 border px-3 sm:px-4 py-1 rounded-lg text-sm sm:text-md font-bold transition-colors flex items-center gap-2'>
|
<button className='bg-[#fff] text-gray-500 border px-3 sm:px-4 py-2 rounded-lg text-sm sm:text-md font-bold transition-colors flex items-center gap-2'>
|
||||||
<img src={Share2} alt="" className='w-4 h-4' />
|
<img src={Share2} alt="" className='w-4 h-4' />
|
||||||
<span>Export</span>
|
<span>Export</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم