From b47009bf46daaa2a27d101b6809738b98be6eac4 Mon Sep 17 00:00:00 2001 From: Musilah Date: Thu, 16 Jan 2025 23:03:06 +0300 Subject: [PATCH 01/12] test: deployment with new pipeline Signed-off-by: Musilah --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index acf6041..64f0527 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "predeploy": "npm run build", "deploy": "gh-pages -d out" }, - "homepage": "https://absmach.github.io/mg-website", + "homepage": "https://Musilah.github.io/mg-website", "dependencies": { "@radix-ui/react-accordion": "^1.2.2", "@radix-ui/react-separator": "^1.1.1", From 8c4f6fa933750ac6db84248cdaab738c28506268 Mon Sep 17 00:00:00 2001 From: Musilah Date: Fri, 24 Jan 2025 11:12:11 +0300 Subject: [PATCH 02/12] refactor components Signed-off-by: Musilah --- public/student-in-the-classroom.svg | 114 +++++++++++ src/app/globals.css | 18 ++ src/app/page.tsx | 97 ++-------- src/components/faq-card.tsx | 56 +++--- src/components/features-card.tsx | 35 +++- src/components/footer-bottom.tsx | 23 +++ src/components/footer-company-info.tsx | 15 ++ src/components/footer-newsletter.tsx | 21 +++ src/components/footer-quick-links.tsx | 21 +++ src/components/footer-social-links.tsx | 34 ++++ src/components/future-features-card.tsx | 25 +++ src/components/ui/footer.tsx | 146 +-------------- src/components/ui/header.tsx | 16 +- src/components/usecase-tab.tsx | 23 ++- src/lib/constants.ts | 239 +++++++++++++++--------- 15 files changed, 542 insertions(+), 341 deletions(-) create mode 100644 public/student-in-the-classroom.svg create mode 100644 src/components/footer-bottom.tsx create mode 100644 src/components/footer-company-info.tsx create mode 100644 src/components/footer-newsletter.tsx create mode 100644 src/components/footer-quick-links.tsx create mode 100644 src/components/footer-social-links.tsx diff --git a/public/student-in-the-classroom.svg b/public/student-in-the-classroom.svg new file mode 100644 index 0000000..10ca2d2 --- /dev/null +++ b/public/student-in-the-classroom.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/globals.css b/src/app/globals.css index b8d6d0b..c2ceafe 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -81,4 +81,22 @@ body { body { @apply bg-background text-foreground; } + html { + font-size: 16px; + } + @media (max-width: 768px) { + html { + font-size: 14px; + } + } + + @media (max-width: 480px) { + html { + font-size: 12px; + } + } + + body { + line-height: 1.5; + } } diff --git a/src/app/page.tsx b/src/app/page.tsx index 492e19a..b791f23 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,17 +1,15 @@ -import { BenefitsSection } from '@/components/benefits-card'; -import { ComingSoonBanner } from '@/components/coming-soonbanner'; -import { FAQCard } from '@/components/faq-card'; -import { ProductFeatureCard } from '@/components/features-card'; -import { Hero } from '@/components/hero'; -import { PoweredBy } from '@/components/powered-by'; -import { UseCasesTabs } from '@/components/usecase-tab'; +import { BenefitsSection } from "@/components/benefits-card"; +import { ComingSoonBanner } from "@/components/coming-soonbanner"; +import { FAQSection } from "@/components/faq-card"; import { - benefitsData, - faqData, - featuresData, - heroData, - useCasesData, -} from '@/lib/constants'; + FeaturesSection, + ProductFeatureCard, +} from "@/components/features-card"; +import { NextFeaturesSection } from "@/components/future-features-card"; +import { Hero } from "@/components/hero"; +import { PoweredBy } from "@/components/powered-by"; +import { heroData } from "@/lib/constants"; +import { UseCasesSection } from "@/components/usecase-tab"; export default function Home() { return ( @@ -32,64 +30,13 @@ export default function Home() { {/* Features Section */} -
-
-

- Explore Our Features -

-

- Discover tools that make your development journey seamless and - scalable. -

- -
- {featuresData.map((feature, index) => ( -
- -
- ))} -
-
-
+ {/* Future Features Section */} - {/*
-
-

Thats not all!

-

- We have a range of exciting new updates still on the drawing board - to look forward to! -

-
- {futureFeaturesData.map((futureFeature, index) => ( - - ))} -
-
-
*/} + {/* Use Cases Tabs */} -
-
-

Use Cases

-

- Here are some real world solutions that Magistrala has aided in - fruition -

- -
-
+ {/* Pricing Section*/} @@ -99,21 +46,7 @@ export default function Home() { {/* FAQ Section */} -
-
-

FAQs

-
- {faqData.map((faqCategory, index) => ( - - ))} -
-
-
+ ); } diff --git a/src/components/faq-card.tsx b/src/components/faq-card.tsx index 72bc6cc..0e447b6 100644 --- a/src/components/faq-card.tsx +++ b/src/components/faq-card.tsx @@ -3,29 +3,43 @@ import { AccordionContent, AccordionItem, AccordionTrigger, -} from '@/components/ui/accordion'; +} from "@/components/ui/accordion"; +import { faqSectionData } from "@/lib/constants"; +import { getImageUrl } from "@/lib/getImageUrl"; -interface FAQCardProps { - title: string; - faqs: { - question: string; - answer: string; - }[]; -} +export function FAQSection() { + const { sectionId, title, faqs } = faqSectionData; + const faqImage = "student-in-the-classroom.svg"; -export function FAQCard({ title, faqs }: FAQCardProps) { return ( -
-

{title}

- - {faqs.map((faq, index) => ( - // biome-ignore lint/suspicious/noArrayIndexKey: - - {faq.question} - {faq.answer} - - ))} - -
+
+
+

{title}

+ {/* FAQ card */} +
+
+ FAQs Illustration +
+
+ + {faqSectionData.faqs.map((faq, index) => ( + + + {faq.question} + + + {faq.answer} + + + ))} + +
+
+
+
); } diff --git a/src/components/features-card.tsx b/src/components/features-card.tsx index 02d0e99..8e93ecd 100644 --- a/src/components/features-card.tsx +++ b/src/components/features-card.tsx @@ -1,5 +1,6 @@ -import { getImageUrl } from '@/lib/getImageUrl'; -import Image from 'next/image'; +import { getImageUrl } from "@/lib/getImageUrl"; +import Image from "next/image"; +import { featuresSectionData } from "@/lib/constants"; interface ProductFeatureCardProps { title: string; @@ -17,7 +18,7 @@ export function ProductFeatureCard({ return (
@@ -36,3 +37,31 @@ export function ProductFeatureCard({
); } + +export function FeaturesSection() { + const { sectionId, title, subtitle, features } = featuresSectionData; + + return ( +
+
+

+ {title} +

+

{subtitle}

+ +
+ {features.map((feature, index) => ( +
+ +
+ ))} +
+
+
+ ); +} diff --git a/src/components/footer-bottom.tsx b/src/components/footer-bottom.tsx new file mode 100644 index 0000000..51e4a7f --- /dev/null +++ b/src/components/footer-bottom.tsx @@ -0,0 +1,23 @@ +import Link from "next/link"; +import { footerData } from "@/lib/constants"; + +export function FooterBottom() { + const { year, rights, policies } = footerData.footerBottom; + + return ( +
+
+

+ © {year} Abstract Machines. {rights} +

+
+ {policies.map((policy, index) => ( + + {policy.label} + + ))} +
+
+
+ ); +} diff --git a/src/components/footer-company-info.tsx b/src/components/footer-company-info.tsx new file mode 100644 index 0000000..db61f0e --- /dev/null +++ b/src/components/footer-company-info.tsx @@ -0,0 +1,15 @@ +import Image from "next/image"; +import { getImageUrl } from "@/lib/getImageUrl"; +import { footerData } from "@/lib/constants"; + +export function FooterCompanyInfo() { + const { logo, name, description } = footerData.companyInfo; + + return ( +
+ {`${name} +

{name}

+

{description}

+
+ ); +} diff --git a/src/components/footer-newsletter.tsx b/src/components/footer-newsletter.tsx new file mode 100644 index 0000000..722a319 --- /dev/null +++ b/src/components/footer-newsletter.tsx @@ -0,0 +1,21 @@ +import { Button } from "@/components/ui/button"; +import { footerData } from "@/lib/constants"; + +export function FooterNewsletter() { + const { title, subtitle, placeholder, buttonText } = footerData.newsletter; + + return ( +
+

{title}

+

{subtitle}

+
+ + +
+
+ ); +} diff --git a/src/components/footer-quick-links.tsx b/src/components/footer-quick-links.tsx new file mode 100644 index 0000000..df6ca53 --- /dev/null +++ b/src/components/footer-quick-links.tsx @@ -0,0 +1,21 @@ +import Link from "next/link"; +import { footerData } from "@/lib/constants"; + +export function FooterQuickLinks() { + return ( +
+

Quick Links

+ +
+ ); +} diff --git a/src/components/footer-social-links.tsx b/src/components/footer-social-links.tsx new file mode 100644 index 0000000..cf76f2d --- /dev/null +++ b/src/components/footer-social-links.tsx @@ -0,0 +1,34 @@ +import { Github, Linkedin, Mail, Twitter } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { footerData } from "@/lib/constants"; + +const icons = { + Twitter, + Linkedin, + Github, + } as const; + +export function FooterSocialLinks() { + return ( +
+

Connect With Us

+
+ {footerData.socialLinks.map((link) => { + const Icon = icons[link.icon as keyof typeof icons]; + return ( + + + {link.platform} + + ); + })} +
+
+ ); +} diff --git a/src/components/future-features-card.tsx b/src/components/future-features-card.tsx index f530212..eaa85f1 100644 --- a/src/components/future-features-card.tsx +++ b/src/components/future-features-card.tsx @@ -1,6 +1,7 @@ import { getImageUrl } from '@/lib/getImageUrl'; import Image from 'next/image'; import { Card, CardDescription, CardHeader, CardTitle } from './ui/card'; +import { nextFeaturesSectionData } from "@/lib/constants"; interface ProductFutureFeatureCardProps { title: string; @@ -31,3 +32,27 @@ export function ProductFutureFeatureCard({ ); } + +export function NextFeaturesSection() { + const { sectionId, title, subtitle, features } = nextFeaturesSectionData; + + return ( +
+
+

{title}

+

{subtitle}

+ +
+ {features.map((feature, index) => ( + + ))} +
+
+
+ ); +} diff --git a/src/components/ui/footer.tsx b/src/components/ui/footer.tsx index 882da9e..8714127 100644 --- a/src/components/ui/footer.tsx +++ b/src/components/ui/footer.tsx @@ -4,6 +4,11 @@ import { getImageUrl } from '@/lib/getImageUrl'; import { Github, Linkedin, Mail, Twitter } from 'lucide-react'; import Image from 'next/image'; import Link from 'next/link'; +import { FooterCompanyInfo } from '../footer-company-info'; +import { FooterQuickLinks } from '../footer-quick-links'; +import { FooterSocialLinks } from '../footer-social-links'; +import { FooterNewsletter } from '../footer-newsletter'; +import { FooterBottom } from '../footer-bottom'; export default function Footer() { return ( @@ -11,145 +16,14 @@ export default function Footer() {
{/* Main Footer Content */}
- {/* Company Info */} -
- Abstract Machines Logo -

Magistrala

-

- Connecting devices, sharing data, and visualizing insights with - our powerful IoT platform built for the future. -

-
- - {/* Quick Links */} -
-

Quick Links

- -
- - {/* Contact & Social Links */} - - - {/* Newsletter Signup */} -
-

Newsletter

-

Stay in the loop

-
- - -
-
+ + + +
{/* Footer Bottom */} -
-
-

- © {new Date().getFullYear()} Abstract Machines. All rights - reserved. -

-
- - Privacy Policy - - - Terms of Service - -
-
-
+
); diff --git a/src/components/ui/header.tsx b/src/components/ui/header.tsx index 8c60472..556dbf9 100644 --- a/src/components/ui/header.tsx +++ b/src/components/ui/header.tsx @@ -1,17 +1,17 @@ -import { Button } from '@/components/ui/button'; -import { navigationLinks } from '@/lib/constants'; -import { getImageUrl } from '@/lib/getImageUrl'; -import Image from 'next/image'; -import Link from 'next/link'; +import { Button } from "@/components/ui/button"; +import { navigationLinks } from "@/lib/constants"; +import { getImageUrl } from "@/lib/getImageUrl"; +import Image from "next/image"; +import Link from "next/link"; export default function Header() { return ( -
+
{/* Logo Section */} Logo {navigationLinks.map((link) => (
  • - + {link.label}
  • diff --git a/src/components/usecase-tab.tsx b/src/components/usecase-tab.tsx index 90c8ac0..10d6537 100644 --- a/src/components/usecase-tab.tsx +++ b/src/components/usecase-tab.tsx @@ -6,6 +6,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { getImageUrl } from '@/lib/getImageUrl'; import Image from 'next/image'; import { useState } from 'react'; +import { useCasesSectionData } from "@/lib/constants"; interface UseCase { title: string; @@ -47,9 +48,11 @@ export function UseCasesTabs({ useCases }: UseCasesTabsProps) {

    {useCase.description}

    - + {useCase.ctaText && useCase.ctaLink && ( + + )} {useCase.secondaryCtaText && useCase.secondaryCtaLink && ( - + + +
    ); From 80632b214487e2c41a0db278a2d2bfab45f3ac70 Mon Sep 17 00:00:00 2001 From: Musilah Date: Fri, 24 Jan 2025 13:50:52 +0300 Subject: [PATCH 04/12] fix favicon Signed-off-by: Musilah --- src/app/favicon.ico | Bin 25931 -> 0 bytes src/app/layout.tsx | 10 +++++++++- src/lib/getImageUrl.ts | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) delete mode 100644 src/app/favicon.ico diff --git a/src/app/favicon.ico b/src/app/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 zcmeHv30#a{`}aL_*G&7qml|y<+KVaDM2m#dVr!KsA!#An?kSQM(q<_dDNCpjEux83 zLb9Z^XxbDl(w>%i@8hT6>)&Gu{h#Oeyszu?xtw#Zb1mO{pgX9699l+Qppw7jXaYf~-84xW z)w4x8?=youko|}Vr~(D$UXIbiXABHh`p1?nn8Po~fxRJv}|0e(BPs|G`(TT%kKVJAdg5*Z|x0leQq0 zkdUBvb#>9F()jo|T~kx@OM8$9wzs~t2l;K=woNssA3l6|sx2r3+kdfVW@e^8e*E}v zA1y5{bRi+3Z`uD3{F7LgFJDdvm;nJilkzDku>BwXH(8ItVCXk*-lSJnR?-2UN%hJ){&rlvg`CDTj z)Bzo!3v7Ou#83zEDEFcKt(f1E0~=rqeEbTnMvWR#{+9pg%7G8y>u1OVRUSoox-ovF z2Ydma(;=YuBY(eI|04{hXzZD6_f(v~H;C~y5=DhAC{MMS>2fm~1H_t2$56pc$NH8( z5bH|<)71dV-_oCHIrzrT`2s-5w_+2CM0$95I6X8p^r!gHp+j_gd;9O<1~CEQQGS8) zS9Qh3#p&JM-G8rHekNmKVewU;pJRcTAog68KYo^dRo}(M>36U4Us zfgYWSiHZL3;lpWT=zNAW>Dh#mB!_@Lg%$ms8N-;aPqMn+C2HqZgz&9~Eu z4|Kp<`$q)Uw1R?y(~S>ePdonHxpV1#eSP1B;Ogo+-Pk}6#0GsZZ5!||ev2MGdh}_m z{DeR7?0-1^zVs&`AV6Vt;r3`I`OI_wgs*w=eO%_#7Kepl{B@xiyCANc(l zzIyd4y|c6PXWq9-|KM8(zIk8LPk(>a)zyFWjhT!$HJ$qX1vo@d25W<fvZQ2zUz5WRc(UnFMKHwe1| zWmlB1qdbiA(C0jmnV<}GfbKtmcu^2*P^O?MBLZKt|As~ge8&AAO~2K@zbXelK|4T<{|y4`raF{=72kC2Kn(L4YyenWgrPiv z@^mr$t{#X5VuIMeL!7Ab6_kG$&#&5p*Z{+?5U|TZ`B!7llpVmp@skYz&n^8QfPJzL z0G6K_OJM9x+Wu2gfN45phANGt{7=C>i34CV{Xqlx(fWpeAoj^N0Biu`w+MVcCUyU* zDZuzO0>4Z6fbu^T_arWW5n!E45vX8N=bxTVeFoep_G#VmNlQzAI_KTIc{6>c+04vr zx@W}zE5JNSU>!THJ{J=cqjz+4{L4A{Ob9$ZJ*S1?Ggg3klFp!+Y1@K+pK1DqI|_gq z5ZDXVpge8-cs!o|;K73#YXZ3AShj50wBvuq3NTOZ`M&qtjj#GOFfgExjg8Gn8>Vq5 z`85n+9|!iLCZF5$HJ$Iu($dm?8~-ofu}tEc+-pyke=3!im#6pk_Wo8IA|fJwD&~~F zc16osQ)EBo58U7XDuMexaPRjU@h8tXe%S{fA0NH3vGJFhuyyO!Uyl2^&EOpX{9As0 zWj+P>{@}jxH)8|r;2HdupP!vie{sJ28b&bo!8`D^x}TE$%zXNb^X1p@0PJ86`dZyj z%ce7*{^oo+6%&~I!8hQy-vQ7E)0t0ybH4l%KltWOo~8cO`T=157JqL(oq_rC%ea&4 z2NcTJe-HgFjNg-gZ$6!Y`SMHrlj}Etf7?r!zQTPPSv}{so2e>Fjs1{gzk~LGeesX%r(Lh6rbhSo_n)@@G-FTQy93;l#E)hgP@d_SGvyCp0~o(Y;Ee8{ zdVUDbHm5`2taPUOY^MAGOw*>=s7=Gst=D+p+2yON!0%Hk` zz5mAhyT4lS*T3LS^WSxUy86q&GnoHxzQ6vm8)VS}_zuqG?+3td68_x;etQAdu@sc6 zQJ&5|4(I?~3d-QOAODHpZ=hlSg(lBZ!JZWCtHHSj`0Wh93-Uk)_S%zsJ~aD>{`A0~ z9{AG(e|q3g5B%wYKRxiL2Y$8(4w6bzchKuloQW#e&S3n+P- z8!ds-%f;TJ1>)v)##>gd{PdS2Oc3VaR`fr=`O8QIO(6(N!A?pr5C#6fc~Ge@N%Vvu zaoAX2&(a6eWy_q&UwOhU)|P3J0Qc%OdhzW=F4D|pt0E4osw;%<%Dn58hAWD^XnZD= z>9~H(3bmLtxpF?a7su6J7M*x1By7YSUbxGi)Ot0P77`}P3{)&5Un{KD?`-e?r21!4vTTnN(4Y6Lin?UkSM z`MXCTC1@4A4~mvz%Rh2&EwY))LeoT=*`tMoqcEXI>TZU9WTP#l?uFv+@Dn~b(>xh2 z;>B?;Tz2SR&KVb>vGiBSB`@U7VIWFSo=LDSb9F{GF^DbmWAfpms8Sx9OX4CnBJca3 zlj9(x!dIjN?OG1X4l*imJNvRCk}F%!?SOfiOq5y^mZW)jFL@a|r-@d#f7 z2gmU8L3IZq0ynIws=}~m^#@&C%J6QFo~Mo4V`>v7MI-_!EBMMtb%_M&kvAaN)@ZVw z+`toz&WG#HkWDjnZE!6nk{e-oFdL^$YnbOCN}JC&{$#$O27@|Tn-skXr)2ml2~O!5 zX+gYoxhoc7qoU?C^3~&!U?kRFtnSEecWuH0B0OvLodgUAi}8p1 zrO6RSXHH}DMc$&|?D004DiOVMHV8kXCP@7NKB zgaZq^^O<7PoKEp72kby@W0Z!Y*Ay{&vfg#C&gG@YVR9g?FEocMUi1gSN$+V+ayF45{a zuDZDTN}mS|;BO%gEf}pjBfN2-gIrU#G5~cucA;dokXW89%>AyXJJI z9X4UlIWA|ZYHgbI z5?oFk@A=Ik7lrEQPDH!H+b`7_Y~aDb_qa=B2^Y&Ow41cU=4WDd40dp5(QS-WMN-=Y z9g;6_-JdNU;|6cPwf$ak*aJIcwL@1n$#l~zi{c{EW?T;DaW*E8DYq?Umtz{nJ&w-M zEMyTDrC&9K$d|kZe2#ws6)L=7K+{ zQw{XnV6UC$6-rW0emqm8wJoeZK)wJIcV?dST}Z;G0Arq{dVDu0&4kd%N!3F1*;*pW zR&qUiFzK=@44#QGw7k1`3t_d8&*kBV->O##t|tonFc2YWrL7_eqg+=+k;!F-`^b8> z#KWCE8%u4k@EprxqiV$VmmtiWxDLgnGu$Vs<8rppV5EajBXL4nyyZM$SWVm!wnCj-B!Wjqj5-5dNXukI2$$|Bu3Lrw}z65Lc=1G z^-#WuQOj$hwNGG?*CM_TO8Bg-1+qc>J7k5c51U8g?ZU5n?HYor;~JIjoWH-G>AoUP ztrWWLbRNqIjW#RT*WqZgPJXU7C)VaW5}MiijYbABmzoru6EmQ*N8cVK7a3|aOB#O& zBl8JY2WKfmj;h#Q!pN%9o@VNLv{OUL?rixHwOZuvX7{IJ{(EdPpuVFoQqIOa7giLVkBOKL@^smUA!tZ1CKRK}#SSM)iQHk)*R~?M!qkCruaS!#oIL1c z?J;U~&FfH#*98^G?i}pA{ z9Jg36t4=%6mhY(quYq*vSxptes9qy|7xSlH?G=S@>u>Ebe;|LVhs~@+06N<4CViBk zUiY$thvX;>Tby6z9Y1edAMQaiH zm^r3v#$Q#2T=X>bsY#D%s!bhs^M9PMAcHbCc0FMHV{u-dwlL;a1eJ63v5U*?Q_8JO zT#50!RD619#j_Uf))0ooADz~*9&lN!bBDRUgE>Vud-i5ck%vT=r^yD*^?Mp@Q^v+V zG#-?gKlr}Eeqifb{|So?HM&g91P8|av8hQoCmQXkd?7wIJwb z_^v8bbg`SAn{I*4bH$u(RZ6*xUhuA~hc=8czK8SHEKTzSxgbwi~9(OqJB&gwb^l4+m`k*Q;_?>Y-APi1{k zAHQ)P)G)f|AyjSgcCFps)Fh6Bca*Xznq36!pV6Az&m{O8$wGFD? zY&O*3*J0;_EqM#jh6^gMQKpXV?#1?>$ml1xvh8nSN>-?H=V;nJIwB07YX$e6vLxH( zqYwQ>qxwR(i4f)DLd)-$P>T-no_c!LsN@)8`e;W@)-Hj0>nJ-}Kla4-ZdPJzI&Mce zv)V_j;(3ERN3_@I$N<^|4Lf`B;8n+bX@bHbcZTopEmDI*Jfl)-pFDvo6svPRoo@(x z);_{lY<;);XzT`dBFpRmGrr}z5u1=pC^S-{ce6iXQlLGcItwJ^mZx{m$&DA_oEZ)B{_bYPq-HA zcH8WGoBG(aBU_j)vEy+_71T34@4dmSg!|M8Vf92Zj6WH7Q7t#OHQqWgFE3ARt+%!T z?oLovLVlnf?2c7pTc)~cc^($_8nyKwsN`RA-23ed3sdj(ys%pjjM+9JrctL;dy8a( z@en&CQmnV(()bu|Y%G1-4a(6x{aLytn$T-;(&{QIJB9vMox11U-1HpD@d(QkaJdEb zG{)+6Dos_L+O3NpWo^=gR?evp|CqEG?L&Ut#D*KLaRFOgOEK(Kq1@!EGcTfo+%A&I z=dLbB+d$u{sh?u)xP{PF8L%;YPPW53+@{>5W=Jt#wQpN;0_HYdw1{ksf_XhO4#2F= zyPx6Lx2<92L-;L5PD`zn6zwIH`Jk($?Qw({erA$^bC;q33hv!d!>%wRhj# zal^hk+WGNg;rJtb-EB(?czvOM=H7dl=vblBwAv>}%1@{}mnpUznfq1cE^sgsL0*4I zJ##!*B?=vI_OEVis5o+_IwMIRrpQyT_Sq~ZU%oY7c5JMIADzpD!Upz9h@iWg_>>~j zOLS;wp^i$-E?4<_cp?RiS%Rd?i;f*mOz=~(&3lo<=@(nR!_Rqiprh@weZlL!t#NCc zO!QTcInq|%#>OVgobj{~ixEUec`E25zJ~*DofsQdzIa@5^nOXj2T;8O`l--(QyU^$t?TGY^7#&FQ+2SS3B#qK*k3`ye?8jUYSajE5iBbJls75CCc(m3dk{t?- zopcER9{Z?TC)mk~gpi^kbbu>b-+a{m#8-y2^p$ka4n60w;Sc2}HMf<8JUvhCL0B&Btk)T`ctE$*qNW8L$`7!r^9T+>=<=2qaq-;ll2{`{Rg zc5a0ZUI$oG&j-qVOuKa=*v4aY#IsoM+1|c4Z)<}lEDvy;5huB@1RJPquU2U*U-;gu z=En2m+qjBzR#DEJDO`WU)hdd{Vj%^0V*KoyZ|5lzV87&g_j~NCjwv0uQVqXOb*QrQ zy|Qn`hxx(58c70$E;L(X0uZZ72M1!6oeg)(cdKO ze0gDaTz+ohR-#d)NbAH4x{I(21yjwvBQfmpLu$)|m{XolbgF!pmsqJ#D}(ylp6uC> z{bqtcI#hT#HW=wl7>p!38sKsJ`r8}lt-q%Keqy%u(xk=yiIJiUw6|5IvkS+#?JTBl z8H5(Q?l#wzazujH!8o>1xtn8#_w+397*_cy8!pQGP%K(Ga3pAjsaTbbXJlQF_+m+-UpUUent@xM zg%jqLUExj~o^vQ3Gl*>wh=_gOr2*|U64_iXb+-111aH}$TjeajM+I20xw(((>fej-@CIz4S1pi$(#}P7`4({6QS2CaQS4NPENDp>sAqD z$bH4KGzXGffkJ7R>V>)>tC)uax{UsN*dbeNC*v}#8Y#OWYwL4t$ePR?VTyIs!wea+ z5Urmc)X|^`MG~*dS6pGSbU+gPJoq*^a=_>$n4|P^w$sMBBy@f*Z^Jg6?n5?oId6f{ z$LW4M|4m502z0t7g<#Bx%X;9<=)smFolV&(V^(7Cv2-sxbxopQ!)*#ZRhTBpx1)Fc zNm1T%bONzv6@#|dz(w02AH8OXe>kQ#1FMCzO}2J_mST)+ExmBr9cva-@?;wnmWMOk z{3_~EX_xadgJGv&H@zK_8{(x84`}+c?oSBX*Ge3VdfTt&F}yCpFP?CpW+BE^cWY0^ zb&uBN!Ja3UzYHK-CTyA5=L zEMW{l3Usky#ly=7px648W31UNV@K)&Ub&zP1c7%)`{);I4b0Q<)B}3;NMG2JH=X$U zfIW4)4n9ZM`-yRj67I)YSLDK)qfUJ_ij}a#aZN~9EXrh8eZY2&=uY%2N0UFF7<~%M zsB8=erOWZ>Ct_#^tHZ|*q`H;A)5;ycw*IcmVxi8_0Xk}aJA^ath+E;xg!x+As(M#0=)3!NJR6H&9+zd#iP(m0PIW8$ z1Y^VX`>jm`W!=WpF*{ioM?C9`yOR>@0q=u7o>BP-eSHqCgMDj!2anwH?s%i2p+Q7D zzszIf5XJpE)IG4;d_(La-xenmF(tgAxK`Y4sQ}BSJEPs6N_U2vI{8=0C_F?@7<(G; zo$~G=8p+076G;`}>{MQ>t>7cm=zGtfbdDXm6||jUU|?X?CaE?(<6bKDYKeHlz}DA8 zXT={X=yp_R;HfJ9h%?eWvQ!dRgz&Su*JfNt!Wu>|XfU&68iRikRrHRW|ZxzRR^`eIGt zIeiDgVS>IeExKVRWW8-=A=yA`}`)ZkWBrZD`hpWIxBGkh&f#ijr449~m`j6{4jiJ*C!oVA8ZC?$1RM#K(_b zL9TW)kN*Y4%^-qPpMP7d4)o?Nk#>aoYHT(*g)qmRUb?**F@pnNiy6Fv9rEiUqD(^O zzyS?nBrX63BTRYduaG(0VVG2yJRe%o&rVrLjbxTaAFTd8s;<<@Qs>u(<193R8>}2_ zuwp{7;H2a*X7_jryzriZXMg?bTuegABb^87@SsKkr2)0Gyiax8KQWstw^v#ix45EVrcEhr>!NMhprl$InQMzjSFH54x5k9qHc`@9uKQzvL4ihcq{^B zPrVR=o_ic%Y>6&rMN)hTZsI7I<3&`#(nl+3y3ys9A~&^=4?PL&nd8)`OfG#n zwAMN$1&>K++c{^|7<4P=2y(B{jJsQ0a#U;HTo4ZmWZYvI{+s;Td{Yzem%0*k#)vjpB zia;J&>}ICate44SFYY3vEelqStQWFihx%^vQ@Do(sOy7yR2@WNv7Y9I^yL=nZr3mb zXKV5t@=?-Sk|b{XMhA7ZGB@2hqsx}4xwCW!in#C zI@}scZlr3-NFJ@NFaJlhyfcw{k^vvtGl`N9xSo**rDW4S}i zM9{fMPWo%4wYDG~BZ18BD+}h|GQKc-g^{++3MY>}W_uq7jGHx{mwE9fZiPCoxN$+7 zrODGGJrOkcPQUB(FD5aoS4g~7#6NR^ma7-!>mHuJfY5kTe6PpNNKC9GGRiu^L31uG z$7v`*JknQHsYB!Tm_W{a32TM099djW%5e+j0Ve_ct}IM>XLF1Ap+YvcrLV=|CKo6S zb+9Nl3_YdKP6%Cxy@6TxZ>;4&nTneadr z_ES90ydCev)LV!dN=#(*f}|ZORFdvkYBni^aLbUk>BajeWIOcmHP#8S)*2U~QKI%S zyrLmtPqb&TphJ;>yAxri#;{uyk`JJqODDw%(Z=2`1uc}br^V%>j!gS)D*q*f_-qf8&D;W1dJgQMlaH5er zN2U<%Smb7==vE}dDI8K7cKz!vs^73o9f>2sgiTzWcwY|BMYHH5%Vn7#kiw&eItCqa zIkR2~Q}>X=Ar8W|^Ms41Fm8o6IB2_j60eOeBB1Br!boW7JnoeX6Gs)?7rW0^5psc- zjS16yb>dFn>KPOF;imD}e!enuIniFzv}n$m2#gCCv4jM#ArwlzZ$7@9&XkFxZ4n!V zj3dyiwW4Ki2QG{@i>yuZXQizw_OkZI^-3otXC{!(lUpJF33gI60ak;Uqitp74|B6I zgg{b=Iz}WkhCGj1M=hu4#Aw173YxIVbISaoc z-nLZC*6Tgivd5V`K%GxhBsp@SUU60-rfc$=wb>zdJzXS&-5(NRRodFk;Kxk!S(O(a0e7oY=E( zAyS;Ow?6Q&XA+cnkCb{28_1N8H#?J!*$MmIwLq^*T_9-z^&UE@A(z9oGYtFy6EZef LrJugUA?W`A8`#=m diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 30cbb1c..36d2d56 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,13 +3,21 @@ import Header from '@/components/ui/header'; import type { Metadata } from 'next'; import { Inter } from 'next/font/google'; import './globals.css'; +import { getImageUrl } from '@/lib/getImageUrl'; const inter = Inter({ subsets: ['latin'] }); export const metadata: Metadata = { title: 'Magistrala', description: 'Connect and Visualize your Devices', -}; + icons: { + icon: [ + { + url: getImageUrl("favicon.png") + } + ] + } + }; export default function RootLayout({ children, diff --git a/src/lib/getImageUrl.ts b/src/lib/getImageUrl.ts index f01d50e..6ba8029 100644 --- a/src/lib/getImageUrl.ts +++ b/src/lib/getImageUrl.ts @@ -1,10 +1,10 @@ const isProd = process.env.NODE_ENV === 'production'; export function getImageUrl(imageUrl: string): string { - const placeholderImage = 'crashed-error.svg'; + const placeholderImage = '/crashed-error.svg'; if (!imageUrl) { - return placeholderImage; + return isProd ? `/mg-website${placeholderImage}` : placeholderImage; } return isProd ? `/mg-website/${imageUrl}` : `/${imageUrl}`; } From f8d9e44ff3ab1bf05555394b84db6d7fd4cf79dc Mon Sep 17 00:00:00 2001 From: Musilah Date: Fri, 24 Jan 2025 16:06:31 +0300 Subject: [PATCH 05/12] add accredition for illustrations Signed-off-by: Musilah --- .../abstract-machines_logo_symbol-white.svg | 1 + src/app/globals.css | 10 - src/app/layout.tsx | 12 +- src/app/page.tsx | 18 +- src/components/faq-card.tsx | 8 +- src/components/features-card.tsx | 8 +- src/components/footer-bottom.tsx | 19 +- src/components/footer-company-info.tsx | 13 +- src/components/footer-newsletter.tsx | 4 +- src/components/footer-quick-links.tsx | 4 +- src/components/footer-social-links.tsx | 22 +- src/components/future-features-card.tsx | 2 +- src/components/hero.tsx | 6 +- src/components/ui/footer.tsx | 14 +- src/components/ui/header.tsx | 34 +-- src/components/usecase-tab.tsx | 2 +- src/lib/constants.ts | 228 +++++++++--------- 17 files changed, 204 insertions(+), 201 deletions(-) create mode 100644 public/abstract-machines_logo_symbol-white.svg diff --git a/public/abstract-machines_logo_symbol-white.svg b/public/abstract-machines_logo_symbol-white.svg new file mode 100644 index 0000000..dfcbb9d --- /dev/null +++ b/public/abstract-machines_logo_symbol-white.svg @@ -0,0 +1 @@ + diff --git a/src/app/globals.css b/src/app/globals.css index 8fb6c55..ad71bfd 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -94,16 +94,6 @@ header { font-size: 14px; } - .header-buttons { - flex-direction: column; - gap: 0.5rem; - } - - .header-buttons a { - width: 100%; - text-align: center; - } - .hero-container { flex-direction: column; text-align: center; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 36d2d56..97ff129 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,9 +1,9 @@ import Footer from '@/components/ui/footer'; import Header from '@/components/ui/header'; +import { getImageUrl } from '@/lib/getImageUrl'; import type { Metadata } from 'next'; import { Inter } from 'next/font/google'; import './globals.css'; -import { getImageUrl } from '@/lib/getImageUrl'; const inter = Inter({ subsets: ['latin'] }); @@ -13,11 +13,11 @@ export const metadata: Metadata = { icons: { icon: [ { - url: getImageUrl("favicon.png") - } - ] - } - }; + url: getImageUrl('favicon.png'), + }, + ], + }, +}; export default function RootLayout({ children, diff --git a/src/app/page.tsx b/src/app/page.tsx index de2485b..fd11e16 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,15 +1,15 @@ -import { BenefitsSection } from "@/components/benefits-card"; -import { ComingSoonBanner } from "@/components/coming-soonbanner"; -import { FAQSection } from "@/components/faq-card"; +import { BenefitsSection } from '@/components/benefits-card'; +import { ComingSoonBanner } from '@/components/coming-soonbanner'; +import { FAQSection } from '@/components/faq-card'; import { FeaturesSection, ProductFeatureCard, -} from "@/components/features-card"; -import { NextFeaturesSection } from "@/components/future-features-card"; -import { Hero } from "@/components/hero"; -import { PoweredBy } from "@/components/powered-by"; -import { heroData } from "@/lib/constants"; -import { UseCasesSection } from "@/components/usecase-tab"; +} from '@/components/features-card'; +import { NextFeaturesSection } from '@/components/future-features-card'; +import { Hero } from '@/components/hero'; +import { PoweredBy } from '@/components/powered-by'; +import { UseCasesSection } from '@/components/usecase-tab'; +import { heroData } from '@/lib/constants'; export default function Home() { return ( diff --git a/src/components/faq-card.tsx b/src/components/faq-card.tsx index 0e447b6..e7d3cf2 100644 --- a/src/components/faq-card.tsx +++ b/src/components/faq-card.tsx @@ -3,13 +3,13 @@ import { AccordionContent, AccordionItem, AccordionTrigger, -} from "@/components/ui/accordion"; -import { faqSectionData } from "@/lib/constants"; -import { getImageUrl } from "@/lib/getImageUrl"; +} from '@/components/ui/accordion'; +import { faqSectionData } from '@/lib/constants'; +import { getImageUrl } from '@/lib/getImageUrl'; export function FAQSection() { const { sectionId, title, faqs } = faqSectionData; - const faqImage = "student-in-the-classroom.svg"; + const faqImage = 'student-in-the-classroom.svg'; return (
    diff --git a/src/components/features-card.tsx b/src/components/features-card.tsx index 8e93ecd..fdd7da4 100644 --- a/src/components/features-card.tsx +++ b/src/components/features-card.tsx @@ -1,6 +1,6 @@ -import { getImageUrl } from "@/lib/getImageUrl"; -import Image from "next/image"; -import { featuresSectionData } from "@/lib/constants"; +import { featuresSectionData } from '@/lib/constants'; +import { getImageUrl } from '@/lib/getImageUrl'; +import Image from 'next/image'; interface ProductFeatureCardProps { title: string; @@ -18,7 +18,7 @@ export function ProductFeatureCard({ return (
    diff --git a/src/components/footer-bottom.tsx b/src/components/footer-bottom.tsx index 51e4a7f..0b16445 100644 --- a/src/components/footer-bottom.tsx +++ b/src/components/footer-bottom.tsx @@ -1,5 +1,5 @@ -import Link from "next/link"; import { footerData } from "@/lib/constants"; +import Link from "next/link"; export function FooterBottom() { const { year, rights, policies } = footerData.footerBottom; @@ -12,12 +12,27 @@ export function FooterBottom() {

    {policies.map((policy, index) => ( - + {policy.label} ))}
    + {/* Accreditation */} +
    + Source:{" "} + + popsy.co + +
    ); } diff --git a/src/components/footer-company-info.tsx b/src/components/footer-company-info.tsx index db61f0e..dd52436 100644 --- a/src/components/footer-company-info.tsx +++ b/src/components/footer-company-info.tsx @@ -1,13 +1,18 @@ -import Image from "next/image"; -import { getImageUrl } from "@/lib/getImageUrl"; -import { footerData } from "@/lib/constants"; +import { footerData } from '@/lib/constants'; +import { getImageUrl } from '@/lib/getImageUrl'; +import Image from 'next/image'; export function FooterCompanyInfo() { const { logo, name, description } = footerData.companyInfo; return (
    - {`${name} + {`${name}

    {name}

    {description}

    diff --git a/src/components/footer-newsletter.tsx b/src/components/footer-newsletter.tsx index 722a319..d9fda98 100644 --- a/src/components/footer-newsletter.tsx +++ b/src/components/footer-newsletter.tsx @@ -1,5 +1,5 @@ -import { Button } from "@/components/ui/button"; -import { footerData } from "@/lib/constants"; +import { Button } from '@/components/ui/button'; +import { footerData } from '@/lib/constants'; export function FooterNewsletter() { const { title, subtitle, placeholder, buttonText } = footerData.newsletter; diff --git a/src/components/footer-quick-links.tsx b/src/components/footer-quick-links.tsx index df6ca53..c4236fe 100644 --- a/src/components/footer-quick-links.tsx +++ b/src/components/footer-quick-links.tsx @@ -1,5 +1,5 @@ -import Link from "next/link"; -import { footerData } from "@/lib/constants"; +import { footerData } from '@/lib/constants'; +import Link from 'next/link'; export function FooterQuickLinks() { return ( diff --git a/src/components/footer-social-links.tsx b/src/components/footer-social-links.tsx index cf76f2d..b13980d 100644 --- a/src/components/footer-social-links.tsx +++ b/src/components/footer-social-links.tsx @@ -1,18 +1,18 @@ -import { Github, Linkedin, Mail, Twitter } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { footerData } from "@/lib/constants"; +import { Button } from '@/components/ui/button'; +import { footerData } from '@/lib/constants'; +import { Github, Linkedin, Mail, Twitter } from 'lucide-react'; const icons = { - Twitter, - Linkedin, - Github, - } as const; + Twitter, + Linkedin, + Github, +} as const; export function FooterSocialLinks() { return ( -
    -

    Connect With Us

    -
    +
    +

    Connect With Us

    +
    {footerData.socialLinks.map((link) => { const Icon = icons[link.icon as keyof typeof icons]; return ( @@ -29,6 +29,6 @@ export function FooterSocialLinks() { ); })}
    -
    +
    ); } diff --git a/src/components/future-features-card.tsx b/src/components/future-features-card.tsx index eaa85f1..387cc9f 100644 --- a/src/components/future-features-card.tsx +++ b/src/components/future-features-card.tsx @@ -1,7 +1,7 @@ +import { nextFeaturesSectionData } from '@/lib/constants'; import { getImageUrl } from '@/lib/getImageUrl'; import Image from 'next/image'; import { Card, CardDescription, CardHeader, CardTitle } from './ui/card'; -import { nextFeaturesSectionData } from "@/lib/constants"; interface ProductFutureFeatureCardProps { title: string; diff --git a/src/components/hero.tsx b/src/components/hero.tsx index 59982e6..2eab046 100644 --- a/src/components/hero.tsx +++ b/src/components/hero.tsx @@ -19,8 +19,8 @@ export function Hero({ imageUrl, }: HeroProps) { return ( -
    -
    +
    +

    {title}

    {subtitle}

    @@ -42,7 +42,7 @@ export function Hero({ alt="Hero Image" fill style={{ objectFit: 'cover' }} - className="w-full max-w-sm h-auto mx-auto rounded-md" + className="rounded-md" />
    diff --git a/src/components/ui/footer.tsx b/src/components/ui/footer.tsx index 8714127..67dddf7 100644 --- a/src/components/ui/footer.tsx +++ b/src/components/ui/footer.tsx @@ -1,22 +1,16 @@ -import { Button } from '@/components/ui/button'; -import { Separator } from '@/components/ui/separator'; -import { getImageUrl } from '@/lib/getImageUrl'; -import { Github, Linkedin, Mail, Twitter } from 'lucide-react'; -import Image from 'next/image'; -import Link from 'next/link'; +import { FooterBottom } from '../footer-bottom'; import { FooterCompanyInfo } from '../footer-company-info'; +import { FooterNewsletter } from '../footer-newsletter'; import { FooterQuickLinks } from '../footer-quick-links'; import { FooterSocialLinks } from '../footer-social-links'; -import { FooterNewsletter } from '../footer-newsletter'; -import { FooterBottom } from '../footer-bottom'; export default function Footer() { return (
    {/* Main Footer Content */} -
    - +
    + diff --git a/src/components/ui/header.tsx b/src/components/ui/header.tsx index f638bfe..0a1ee2d 100644 --- a/src/components/ui/header.tsx +++ b/src/components/ui/header.tsx @@ -1,17 +1,17 @@ -import { Button } from "@/components/ui/button"; -import { navigationLinks } from "@/lib/constants"; -import { getImageUrl } from "@/lib/getImageUrl"; -import Image from "next/image"; -import Link from "next/link"; +import { Button } from '@/components/ui/button'; +import { navigationLinks } from '@/lib/constants'; +import { getImageUrl } from '@/lib/getImageUrl'; +import Image from 'next/image'; +import Link from 'next/link'; export default function Header() { return (
    -
    +
    {/* Logo Section */} Logo {/* Navigation Section */} -
    ); diff --git a/src/components/usecase-tab.tsx b/src/components/usecase-tab.tsx index 10d6537..007a80d 100644 --- a/src/components/usecase-tab.tsx +++ b/src/components/usecase-tab.tsx @@ -3,10 +3,10 @@ import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { useCasesSectionData } from '@/lib/constants'; import { getImageUrl } from '@/lib/getImageUrl'; import Image from 'next/image'; import { useState } from 'react'; -import { useCasesSectionData } from "@/lib/constants"; interface UseCase { title: string; diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 6e8fc32..78454c4 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -1,52 +1,52 @@ export const featuresSectionData = { - sectionId: "features", - title: "Explore Our Features", + sectionId: 'features', + title: 'Explore Our Features', subtitle: - "Discover tools that make your development journey seamless and scalable.", + 'Discover tools that make your development journey seamless and scalable.', features: [ - { - title: 'Data Visualization', - description: - 'Magistrala takes data visualization to the next level with customizable dashboards that provide real-time insights into the metrics that matter most to your business. Access a variety of charts, gauges, and control systems to monitor your devices effortlessly. Track and map your devices globally using advanced location services with marker and route maps. Shareable dashboards make it easy to collaborate with your team and keep everyone informed, no matter where they are.', - imageUrl: 'visual-person.svg', - }, - { - title: 'Efficient and Cloud-Native', - description: - 'Leverage a microservices-based, cloud-native architecture for scalable and efficient IoT application deployment.', - imageUrl: 'scalability.svg', - }, - { - title: 'Rules Engine', - description: - 'Implement business logic and trigger custom actions in real-time with the built-in rules engine. The Rules Engine empowers you to create dynamic, event-driven solutions tailored to your specific needs, ensuring complete control over your operations.', - imageUrl: 'calculator.svg', - }, - { - title: 'UI and Open APIs', - description: - "Magistrala provides access to a User Interface which enables to quickly build, edit and share any dashboard data without needing any code basics. There are also well-documented open API's that enable you to integrate Magistrala easily into your own existing systems.", - imageUrl: 'ui-woman-with-a-laptop.svg', - }, - { - title: 'Superior Security', - description: - 'Magistrala is built with security at its core, ensuring the protection and integrity of your data across diverse ecosystems. Advanced encryption, authentication, and fine-grained access control mechanisms safeguard sensitive information. The platform leverages access tokens for secure, token-based authentication and integrates with Google Zanzibar for distributed policy management, enabling scalable, granular access policies. Whether for IoT or enterprise systems, Magistrala provides the confidence to innovate without compromising security.', - imageUrl: 'abstract-art-5.svg', - }, - { - title: 'Readers and Writers', - description: - 'Magistrala enables seamless communication across diverse ecosystems with its powerful readers and writers framework. Utilize industry-leading tools like TimescaleDB, RabbitMQ, Mosquitto, and CoAPCLI to handle both message ingestion and delivery with ease. With full support for scalable databases and message brokers, you can ensure reliable data flow, optimized performance, and flexibility for your unique needs.', - imageUrl: 'searching-location-on-the-phone.svg', - }, - { - title: 'Multi-Protocol Messaging', - description: - 'The Magistrala Platform is a cutting-edge SaaS solution designed to streamline communication between devices, applications, and systems, regardless of their underlying protocols such as http or mqtt. Built with multi-protocol messaging capabilities, it empowers businesses to handle data exchange across diverse infrastructures — from IoT ecosystems to cloud-based applications and enterprise software.', - imageUrl: 'surreal-hourglass.svg', - }, -], + { + title: 'Data Visualization', + description: + 'Magistrala takes data visualization to the next level with customizable dashboards that provide real-time insights into the metrics that matter most to your business. Access a variety of charts, gauges, and control systems to monitor your devices effortlessly. Track and map your devices globally using advanced location services with marker and route maps. Shareable dashboards make it easy to collaborate with your team and keep everyone informed, no matter where they are.', + imageUrl: 'visual-person.svg', + }, + { + title: 'Efficient and Cloud-Native', + description: + 'Leverage a microservices-based, cloud-native architecture for scalable and efficient IoT application deployment.', + imageUrl: 'scalability.svg', + }, + { + title: 'Rules Engine', + description: + 'Implement business logic and trigger custom actions in real-time with the built-in rules engine. The Rules Engine empowers you to create dynamic, event-driven solutions tailored to your specific needs, ensuring complete control over your operations.', + imageUrl: 'calculator.svg', + }, + { + title: 'UI and Open APIs', + description: + "Magistrala provides access to a User Interface which enables to quickly build, edit and share any dashboard data without needing any code basics. There are also well-documented open API's that enable you to integrate Magistrala easily into your own existing systems.", + imageUrl: 'ui-woman-with-a-laptop.svg', + }, + { + title: 'Superior Security', + description: + 'Magistrala is built with security at its core, ensuring the protection and integrity of your data across diverse ecosystems. Advanced encryption, authentication, and fine-grained access control mechanisms safeguard sensitive information. The platform leverages access tokens for secure, token-based authentication and integrates with Google Zanzibar for distributed policy management, enabling scalable, granular access policies. Whether for IoT or enterprise systems, Magistrala provides the confidence to innovate without compromising security.', + imageUrl: 'abstract-art-5.svg', + }, + { + title: 'Readers and Writers', + description: + 'Magistrala enables seamless communication across diverse ecosystems with its powerful readers and writers framework. Utilize industry-leading tools like TimescaleDB, RabbitMQ, Mosquitto, and CoAPCLI to handle both message ingestion and delivery with ease. With full support for scalable databases and message brokers, you can ensure reliable data flow, optimized performance, and flexibility for your unique needs.', + imageUrl: 'searching-location-on-the-phone.svg', + }, + { + title: 'Multi-Protocol Messaging', + description: + 'The Magistrala Platform is a cutting-edge SaaS solution designed to streamline communication between devices, applications, and systems, regardless of their underlying protocols such as http or mqtt. Built with multi-protocol messaging capabilities, it empowers businesses to handle data exchange across diverse infrastructures — from IoT ecosystems to cloud-based applications and enterprise software.', + imageUrl: 'surreal-hourglass.svg', + }, + ], }; export const benefitsData = [ @@ -98,68 +98,67 @@ export const benefitsSectionData = { }; export const nextFeaturesSectionData = { - sectionId: "next-features", + sectionId: 'next-features', title: "That's not all!", subtitle: - "We have a range of exciting new updates still on the drawing board to look forward to!", + 'We have a range of exciting new updates still on the drawing board to look forward to!', features: [ { - title: "Rules Engine", + title: 'Rules Engine', description: - "Implement business logic and trigger custom actions in real-time with the built-in rules engine. The Rules Engine empowers you to create dynamic, event-driven solutions tailored to your specific needs, ensuring complete control over your operations.", - imageUrl: "calculator.svg", + 'Implement business logic and trigger custom actions in real-time with the built-in rules engine. The Rules Engine empowers you to create dynamic, event-driven solutions tailored to your specific needs, ensuring complete control over your operations.', + imageUrl: 'calculator.svg', }, { - title: "1 Lorem ipsum dolor sit amet", + title: '1 Lorem ipsum dolor sit amet', description: - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", - imageUrl: "premium_vector.avif", + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', + imageUrl: 'premium_vector.avif', }, { - title: "2 Lorem ipsum dolor sit amet", + title: '2 Lorem ipsum dolor sit amet', description: - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", - imageUrl: "iot-phone.jpg", + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.', + imageUrl: 'iot-phone.jpg', }, ], }; - export const useCasesSectionData = { - sectionId: "use-cases", - title: "Use Cases", - subtitle: "Here are some real-world solutions that Magistrala has aided in fruition.", + sectionId: 'use-cases', + title: 'Use Cases', + subtitle: + 'Here are some real-world solutions that Magistrala has aided in fruition.', useCases: [ { - title: "Smart Cities", + title: 'Smart Cities', description: - "Manage traffic flow, monitor air quality, and optimize energy usage across urban environments.", - imageUrl: "smart-city2.avif", - ctaText: "Learn more", - ctaLink: "#", - secondaryCtaText: "View demo", - secondaryCtaLink: "/demo/smart-cities", + 'Manage traffic flow, monitor air quality, and optimize energy usage across urban environments.', + imageUrl: 'smart-city2.avif', + ctaText: 'Learn more', + ctaLink: '#', + secondaryCtaText: 'View demo', + secondaryCtaLink: '/demo/smart-cities', }, { - title: "Smart Energy", + title: 'Smart Energy', description: - "Deliver and store data from smart meters in reliable and fault-tolerant way, visualize real-time and historical energy consumption data on customizable end-user dashboards.", - imageUrl: "smart-home.jpg", - ctaText: "See more about Smart energy", - ctaLink: "#", + 'Deliver and store data from smart meters in reliable and fault-tolerant way, visualize real-time and historical energy consumption data on customizable end-user dashboards.', + imageUrl: 'smart-home.jpg', + ctaText: 'See more about Smart energy', + ctaLink: '#', }, { - title: "Industrial IoT", + title: 'Industrial IoT', description: - "Monitor and control industrial equipment, optimize production processes, and predict maintenance needs in real-time.", - imageUrl: "more-dashboards.jpg", - ctaText: "Explore Industrial IoT", - ctaLink: "#", + 'Monitor and control industrial equipment, optimize production processes, and predict maintenance needs in real-time.', + imageUrl: 'more-dashboards.jpg', + ctaText: 'Explore Industrial IoT', + ctaLink: '#', }, ], }; - export const pricingData = [ { title: 'Trial', @@ -193,38 +192,37 @@ export const pricingData = [ ]; export const faqSectionData = { - sectionId: "faq", - title: "FAQs", + sectionId: 'faq', + title: 'FAQs', faqs: [ { - question: "What protocols does the platform support?", + question: 'What protocols does the platform support?', answer: "Our platform supports a wide range of protocols including MQTT, HTTP, CoAP, and more. We're constantly adding support for new protocols to ensure compatibility with various devices.", }, { - question: "How secure is the data transmission?", + question: 'How secure is the data transmission?', answer: - "We implement industry-standard encryption protocols and security measures to ensure that all data transmitted through our platform is secure. This includes end-to-end encryption and regular security audits.", + 'We implement industry-standard encryption protocols and security measures to ensure that all data transmitted through our platform is secure. This includes end-to-end encryption and regular security audits.', }, { - question: "Can I integrate with existing systems?", + question: 'Can I integrate with existing systems?', answer: - "Yes, our platform is designed to be highly integrable. We offer APIs and SDKs that allow you to easily integrate with your existing systems and workflows.", + 'Yes, our platform is designed to be highly integrable. We offer APIs and SDKs that allow you to easily integrate with your existing systems and workflows.', }, { - question: "What are the available pricing plans?", + question: 'What are the available pricing plans?', answer: - "We offer flexible pricing plans tailored to your needs. Visit our pricing section for detailed information.", + 'We offer flexible pricing plans tailored to your needs. Visit our pricing section for detailed information.', }, { - question: "How do I upgrade my plan?", + question: 'How do I upgrade my plan?', answer: - "You can upgrade your plan directly from your billing page. Select the desired plan and complete the payment process.", + 'You can upgrade your plan directly from your billing page. Select the desired plan and complete the payment process.', }, ], }; - export const heroData = { title: 'Simplify Messaging and Empower Systems', subtitle: @@ -280,49 +278,49 @@ export const navigationLinks = [ export const footerData = { companyInfo: { - logo: "abstract-machines_logo_landscape-black.svg", - name: "Magistrala", + logo: 'abstract-machines_logo_landscape-black.svg', + name: 'Magistrala', description: - "Connecting devices, sharing data, and visualizing insights with our powerful IoT platform built for the future.", + 'Connecting devices, sharing data, and visualizing insights with our powerful IoT platform built for the future.', }, quickLinks: [ - { label: "Features", href: "#features" }, - { label: "FAQ", href: "#faq" }, - { label: "Use Cases", href: "#use-cases" }, - { label: "Pricing", href: "#pricing" }, + { label: 'Features', href: '#features' }, + { label: 'FAQ', href: '#faq' }, + { label: 'Use Cases', href: '#use-cases' }, + { label: 'Pricing', href: '#pricing' }, ], socialLinks: [ { - platform: "Twitter", - icon: "Twitter", - href: "https://twitter.com/absmach", + platform: 'Twitter', + icon: 'Twitter', + href: 'https://twitter.com/absmach', }, { - platform: "LinkedIn", - icon: "Linkedin", - href: "https://www.linkedin.com/company/abstract-machines", + platform: 'LinkedIn', + icon: 'Linkedin', + href: 'https://www.linkedin.com/company/abstract-machines', }, { - platform: "GitHub", - icon: "Github", - href: "https://github.com/absmach/magistrala", + platform: 'GitHub', + icon: 'Github', + href: 'https://github.com/absmach/magistrala', }, ], contact: { - email: "info@abstractmachines.fr", + email: 'info@abstractmachines.fr', }, newsletter: { - title: "Newsletter", - subtitle: "Stay in the loop", - placeholder: "Your email address", - buttonText: "Sign Up", + title: 'Newsletter', + subtitle: 'Stay in the loop', + placeholder: 'Your email address', + buttonText: 'Sign Up', }, footerBottom: { year: new Date().getFullYear(), - rights: "All rights reserved.", + rights: 'All rights reserved.', policies: [ - { label: "Privacy Policy", href: "#" }, - { label: "Terms of Service", href: "#" }, + { label: 'Privacy Policy', href: '#' }, + { label: 'Terms of Service', href: '#' }, ], }, }; From 0f44209a5660eb78ef0e1768bd0a06c29de76266 Mon Sep 17 00:00:00 2001 From: Musilah Date: Fri, 24 Jan 2025 19:42:24 +0300 Subject: [PATCH 06/12] fix hero and header Signed-off-by: Musilah --- src/app/globals.css | 36 -------------------------- src/components/benefits-card.tsx | 8 +++--- src/components/features-card.tsx | 8 +++--- src/components/footer-bottom.tsx | 2 +- src/components/footer-company-info.tsx | 2 +- src/components/hero.tsx | 24 ++++++++--------- src/components/powered-by.tsx | 2 +- src/components/ui/header.tsx | 3 +++ src/components/usecase-tab.tsx | 8 +++--- src/lib/constants.ts | 2 +- 10 files changed, 31 insertions(+), 64 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index ad71bfd..420cb22 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -4,11 +4,6 @@ body { font-family: Rubik, sans-serif; - font-size: 18px; -} - -header { - font-size: 21px; } @layer base { @@ -86,35 +81,4 @@ header { body { @apply bg-background text-foreground; } - html { - font-size: 16px; - } - @media (max-width: 768px) { - html { - font-size: 14px; - } - - .hero-container { - flex-direction: column; - text-align: center; - padding: 1rem; - } - - .hero-text { - margin-bottom: 1rem; - } - } - - @media (max-width: 480px) { - html { - font-size: 12px; - } - header img { - width: 150px; - } - } - - body { - line-height: 1.5; - } } diff --git a/src/components/benefits-card.tsx b/src/components/benefits-card.tsx index 6a42a88..9b3cf14 100644 --- a/src/components/benefits-card.tsx +++ b/src/components/benefits-card.tsx @@ -30,10 +30,10 @@ export function ProductBenefitsCard({ {/* Content */}
    - + {title} - + {description} @@ -48,8 +48,8 @@ export function BenefitsSection() { return (
    -

    {title}

    -

    {subtitle}

    +

    {title}

    +

    {subtitle}

    {benefits.map((benefit, index) => ( diff --git a/src/components/features-card.tsx b/src/components/features-card.tsx index fdd7da4..27bab9e 100644 --- a/src/components/features-card.tsx +++ b/src/components/features-card.tsx @@ -22,8 +22,8 @@ export function ProductFeatureCard({ }`} >
    -

    {title}

    -

    {description}

    +

    {title}

    +

    {description}

    -

    +

    {title}

    -

    {subtitle}

    +

    {subtitle}

    {features.map((feature, index) => ( diff --git a/src/components/footer-bottom.tsx b/src/components/footer-bottom.tsx index 0b16445..9913782 100644 --- a/src/components/footer-bottom.tsx +++ b/src/components/footer-bottom.tsx @@ -24,7 +24,7 @@ export function FooterBottom() {
    {/* Accreditation */}
    - Source:{" "} + Illustrations by:{" "} -

    {name}

    + {/*

    {name}

    */}

    {description}

    ); diff --git a/src/components/hero.tsx b/src/components/hero.tsx index 2eab046..de0358c 100644 --- a/src/components/hero.tsx +++ b/src/components/hero.tsx @@ -1,7 +1,7 @@ -import { Button } from '@/components/ui/button'; -import { getImageUrl } from '@/lib/getImageUrl'; -import { ArrowRightCircleIcon } from 'lucide-react'; -import Image from 'next/image'; +import { Button } from "@/components/ui/button"; +import { getImageUrl } from "@/lib/getImageUrl"; +import { ArrowRightCircleIcon } from "lucide-react"; +import Image from "next/image"; interface HeroProps { title: string; @@ -19,15 +19,15 @@ export function Hero({ imageUrl, }: HeroProps) { return ( -
    -
    -
    -

    {title}

    -

    {subtitle}

    +
    +
    + -
    +
    Hero Image
    diff --git a/src/components/powered-by.tsx b/src/components/powered-by.tsx index b78a580..f42ca96 100644 --- a/src/components/powered-by.tsx +++ b/src/components/powered-by.tsx @@ -43,7 +43,7 @@ export function PoweredBy() { return (
    -

    +

    POWERED BY

    diff --git a/src/components/ui/header.tsx b/src/components/ui/header.tsx index 0a1ee2d..28fc84c 100644 --- a/src/components/ui/header.tsx +++ b/src/components/ui/header.tsx @@ -49,3 +49,6 @@ export default function Header() {
    ); } + + +// can have desktop nav and a small one for the small screems which is hidden when we have a large screen \ No newline at end of file diff --git a/src/components/usecase-tab.tsx b/src/components/usecase-tab.tsx index 007a80d..8e678a9 100644 --- a/src/components/usecase-tab.tsx +++ b/src/components/usecase-tab.tsx @@ -43,10 +43,10 @@ export function UseCasesTabs({ useCases }: UseCasesTabsProps) {
    -

    +

    {useCase.title}

    -

    {useCase.description}

    +

    {useCase.description}

    {useCase.ctaText && useCase.ctaLink && (
    diff --git a/src/components/powered-by.tsx b/src/components/powered-by.tsx index f42ca96..198071d 100644 --- a/src/components/powered-by.tsx +++ b/src/components/powered-by.tsx @@ -1,45 +1,8 @@ -import { getImageUrl } from '@/lib/getImageUrl'; +import { poweredByPartners } from '@/lib/constants'; +import { getImageUrl } from '@/lib/utils'; import Image from 'next/image'; export function PoweredBy() { - const partners = [ - { - name: 'Next.js', - imageUrl: 'next.svg', - width: 40, - height: 40, - link: 'https://nextjs.org', - }, - { - name: 'Go', - imageUrl: 'go.svg', - width: 40, - height: 40, - link: 'https://golang.org', - }, - { - name: 'ShadCN', - imageUrl: 'shadcn.svg', - width: 40, - height: 40, - link: 'https://ui.shadcn.com/', - }, - { - name: 'Abstract Machines', - imageUrl: 'abstract-machines_logo_square-black.svg', - width: 40, - height: 40, - link: 'https://github.com/absmach', - }, - { - name: 'Stripe', - imageUrl: 'stripe.svg', - width: 40, - height: 40, - link: 'https://stripe.com', - }, - ]; - return (
    @@ -47,13 +10,13 @@ export function PoweredBy() { POWERED BY
    - {partners.map((partner) => ( + {poweredByPartners.map((partner) => ( -

    {title}

    -
      - {features.map((feature, index) => ( - // biome-ignore lint/suspicious/noArrayIndexKey: This is needed for the constants -
    • - - {feature} -
    • - ))} -
    -
    - - ); -} diff --git a/src/components/pricing-section.tsx b/src/components/pricing-section.tsx deleted file mode 100644 index 95609c1..0000000 --- a/src/components/pricing-section.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { PricingCard } from './pricing-card'; - -interface PricingSectionProps { - plans: Array<{ - title: string; - features: string[]; - ctaText: string; - ctaVariant: 'default' | 'success'; - ctaLink: string; - }>; -} - -export function PricingSection({ plans }: PricingSectionProps) { - return ( -
    -
    -

    Pricing

    -

    - Choose the plan that best fits your needs -

    -
    - {plans.map((plan) => ( - - ))} -
    -
    -
    - ); -} diff --git a/src/components/benefits-card.tsx b/src/components/section-benefits.tsx similarity index 93% rename from src/components/benefits-card.tsx rename to src/components/section-benefits.tsx index 9b3cf14..6256825 100644 --- a/src/components/benefits-card.tsx +++ b/src/components/section-benefits.tsx @@ -1,5 +1,5 @@ import { benefitsSectionData } from '@/lib/constants'; -import { getImageUrl } from '@/lib/getImageUrl'; +import { getImageUrl } from '@/lib/utils'; import { Card, CardDescription, CardHeader, CardTitle } from './ui/card'; interface ProductBenefitsCardProps { @@ -48,7 +48,9 @@ export function BenefitsSection() { return (
    -

    {title}

    +

    + {title} +

    {subtitle}

    diff --git a/src/components/section-faq.tsx b/src/components/section-faq.tsx new file mode 100644 index 0000000..5704f15 --- /dev/null +++ b/src/components/section-faq.tsx @@ -0,0 +1,43 @@ +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from '@/components/ui/accordion'; +import { faqData } from '@/lib/constants'; + +export function FAQSection() { + return ( +
    +
    +

    + FAQs +

    +
    + {faqData.map((faqCategory, index) => ( +
    +

    + {faqCategory.title} +

    + + {faqCategory.faqs.map((faq, faqIndex) => ( + + + {faq.question} + + + {faq.answer} + + + ))} + +
    + ))} +
    +
    +
    + ); +} diff --git a/src/components/features-card.tsx b/src/components/section-features.tsx similarity index 92% rename from src/components/features-card.tsx rename to src/components/section-features.tsx index 27bab9e..239d026 100644 --- a/src/components/features-card.tsx +++ b/src/components/section-features.tsx @@ -1,5 +1,5 @@ import { featuresSectionData } from '@/lib/constants'; -import { getImageUrl } from '@/lib/getImageUrl'; +import { getImageUrl } from '@/lib/utils'; import Image from 'next/image'; interface ProductFeatureCardProps { @@ -47,7 +47,9 @@ export function FeaturesSection() {

    {title}

    -

    {subtitle}

    +

    + {subtitle} +

    {features.map((feature, index) => ( diff --git a/src/components/future-features-card.tsx b/src/components/section-future-features.tsx similarity index 79% rename from src/components/future-features-card.tsx rename to src/components/section-future-features.tsx index 387cc9f..22b6b62 100644 --- a/src/components/future-features-card.tsx +++ b/src/components/section-future-features.tsx @@ -1,5 +1,5 @@ import { nextFeaturesSectionData } from '@/lib/constants'; -import { getImageUrl } from '@/lib/getImageUrl'; +import { getImageUrl } from '@/lib/utils'; import Image from 'next/image'; import { Card, CardDescription, CardHeader, CardTitle } from './ui/card'; @@ -24,8 +24,10 @@ export function ProductFutureFeatureCard({ className="object-cover w-full h-60" /> - {title} - + + {title} + + {description} @@ -39,8 +41,8 @@ export function NextFeaturesSection() { return (
    -

    {title}

    -

    {subtitle}

    +

    {title}

    +

    {subtitle}

    {features.map((feature, index) => ( diff --git a/src/components/section-pricing.tsx b/src/components/section-pricing.tsx new file mode 100644 index 0000000..f5dacff --- /dev/null +++ b/src/components/section-pricing.tsx @@ -0,0 +1,77 @@ +import { Button } from '@/components/ui/button'; +import { Card } from '@/components/ui/card'; +import type { PricingCardProps } from '@/types/card-types'; +import { Check } from 'lucide-react'; + +interface PricingSectionProps { + plans: Array<{ + title: string; + features: string[]; + ctaText: string; + ctaVariant: 'default' | 'success'; + ctaLink: string; + }>; +} + +export interface PricingPlan { + title: string; + features: string[]; + ctaText: string; + ctaVariant: 'default' | 'success'; + ctaLink: string; +} + +// export interface PricingCardProps extends PricingPlan {} + +// export interface PricingSectionProps { +// plans: PricingPlan[]; +// } + +export function PricingCard({ + title, + features, + ctaText, + ctaLink, +}: PricingCardProps) { + return ( + +

    {title}

    +
      + {features.map((feature, index) => ( + // biome-ignore lint/suspicious/noArrayIndexKey: This is needed for the constants +
    • + + {feature} +
    • + ))} +
    + +
    + ); +} + +export function PricingSection({ plans }: PricingSectionProps) { + return ( +
    +
    +

    + Pricing +

    +

    + Choose the plan that best fits your needs +

    +
    + {plans.map((plan) => ( + + ))} +
    +
    +
    + ); +} diff --git a/src/components/ui/footer.tsx b/src/components/ui/footer.tsx index 67dddf7..43cb842 100644 --- a/src/components/ui/footer.tsx +++ b/src/components/ui/footer.tsx @@ -1,5 +1,5 @@ -import { FooterBottom } from '../footer-bottom'; import { FooterCompanyInfo } from '../footer-company-info'; +import { FooterCopyright } from '../footer-copyright'; import { FooterNewsletter } from '../footer-newsletter'; import { FooterQuickLinks } from '../footer-quick-links'; import { FooterSocialLinks } from '../footer-social-links'; @@ -17,7 +17,7 @@ export default function Footer() {
    {/* Footer Bottom */} - +
    ); diff --git a/src/components/ui/header.tsx b/src/components/ui/header.tsx index 28fc84c..4d24e75 100644 --- a/src/components/ui/header.tsx +++ b/src/components/ui/header.tsx @@ -1,27 +1,33 @@ +'use client'; + import { Button } from '@/components/ui/button'; import { navigationLinks } from '@/lib/constants'; -import { getImageUrl } from '@/lib/getImageUrl'; +import { getImageUrl } from '@/lib/utils'; +import { Menu, X } from 'lucide-react'; import Image from 'next/image'; import Link from 'next/link'; +import { useState } from 'react'; export default function Header() { + const [isMenuOpen, setIsMenuOpen] = useState(false); + return (
    -
    +
    {/* Logo Section */} - + Logo - {/* Navigation Section */} + {/* Desktop Navigation Section */} - {/* Button Section */} - + {/* CTA Button Section */} +
    + + + + + {/* Mobile Menu Button */} - +
    + + {/* Mobile Navigation */} + {isMenuOpen && ( + + )}
    ); } - - -// can have desktop nav and a small one for the small screems which is hidden when we have a large screen \ No newline at end of file diff --git a/src/components/usecase-tab.tsx b/src/components/usecase-tab.tsx index 8e678a9..dc25623 100644 --- a/src/components/usecase-tab.tsx +++ b/src/components/usecase-tab.tsx @@ -4,7 +4,7 @@ import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { useCasesSectionData } from '@/lib/constants'; -import { getImageUrl } from '@/lib/getImageUrl'; +import { getImageUrl } from '@/lib/utils'; import Image from 'next/image'; import { useState } from 'react'; @@ -46,7 +46,9 @@ export function UseCasesTabs({ useCases }: UseCasesTabsProps) {

    {useCase.title}

    -

    {useCase.description}

    +

    + {useCase.description} +

    {useCase.ctaText && useCase.ctaLink && (