+
+
+
{t("title")}
-
-
-
-
- {t("mail")}
-
-
-
-
- hello@mikn.dev
-
-
-
- billing@mikn.dev
-
-
-
- abuse@mikn.dev
-
-
-
-
-
-
-
-
-
- {t("phone")}
-
-
- +81 090-9276-3628
-
-
-
-
-
-
-
-
- {t("discord")}
-
-
-
-
-
-
-
-
-
- {t("phone-disclaimer")}
+
+ {contactCards.map((card, index) => (
+
+ ))}
+
);
diff --git a/src/app/[locale]/(pages)/solutions/page.tsx b/src/app/[locale]/(pages)/solutions/page.tsx
new file mode 100644
index 0000000..66e3d2b
--- /dev/null
+++ b/src/app/[locale]/(pages)/solutions/page.tsx
@@ -0,0 +1,121 @@
+import { useTranslations } from "next-intl";
+import DecryptedText from "@/components/DecryptedText";
+import { OSSProductCard } from "@/components/OSSProductCard";
+import KaraSnapIcon from "@/assets/img/karasnap.png";
+import MikanBotIcon from "@/assets/img/mikanbot.png";
+import { IdCard, Rss, MessageSquare, Image, Gamepad } from "lucide-react";
+import { SiDiscord } from "@icons-pack/react-simple-icons";
+
+export default function SolutionsPage() {
+ const t = useTranslations("solutions");
+
+ const sections = [
+ {
+ key: "main",
+ products: [
+ {
+ key: "karaSnap",
+ icon: KaraSnapIcon.src,
+ repoUrl: "https://github.com/mikndotdev/karasnap",
+ websiteUrl: "https://karasnap.mikn.dev",
+ tagKeys: ["fun", "ai"],
+ },
+ {
+ key: "nextDiscordAuth",
+ icon: IdCard,
+ repoUrl: "https://github.com/mikndotdev/next-discord-auth",
+ websiteUrl: "https://npm.im/@mikandev/next-discord-auth",
+ tagKeys: ["dev", "lib"],
+ },
+ {
+ key: "rssfetch",
+ icon: Rss,
+ repoUrl: "https://github.com/mikndotdev/rssfetch",
+ websiteUrl: "https://rssfetch.vercel.app",
+ tagKeys: ["dev", "api"],
+ },
+ {
+ key: "mikanbot",
+ icon: MikanBotIcon.src,
+ repoUrl: "https://github.com/mikndotdev/mikanbot-project",
+ websiteUrl: "/solutions/mikanbot",
+ tagKeys: ["fun", "bot"],
+ },
+ {
+ key: "customrp",
+ icon: SiDiscord,
+ repoUrl: "https://github.com/mikndotdev/customrp",
+ websiteUrl: "https://customrp.mikn.dev",
+ tagKeys: ["fun"],
+ },
+ {
+ key: "enkabadges",
+ icon: Gamepad,
+ repoUrl: "https://github.com/mikndotdev/enkabadges",
+ websiteUrl: "https://enkabadges.mikn.dev",
+ tagKeys: ["fun"],
+ },
+ ],
+ },
+ {
+ key: "legacy",
+ products: [
+ {
+ key: "chat",
+ icon: MessageSquare,
+ repoUrl: "https://github.com/mikndotdev/chat",
+ tagKeys: ["ai"],
+ },
+ {
+ key: "sukushocloud",
+ icon: Image,
+ repoUrl: "https://github.com/mikndotdev/sukushocloud-web",
+ tagKeys: ["api", "fun"],
+ },
+ ],
+ },
+ ];
+
+ return (
+
+
+ {sections.map((section, sectionIndex) => (
+
+
+
+
+
+ {t(`${section.key}.description`)}
+
+
+ {section.products.map((product, productIndex) => (
+ t(`tags.${tagKey}`))}
+ />
+ ))}
+
+
+ ))}
+
+
+ );
+}
diff --git a/src/assets/img/MiknCursor.png b/src/assets/img/MiknCursor.png
new file mode 100644
index 0000000..bf797a8
Binary files /dev/null and b/src/assets/img/MiknCursor.png differ
diff --git a/src/assets/img/mikanbot.png b/src/assets/img/mikanbot.png
new file mode 100644
index 0000000..84e519f
Binary files /dev/null and b/src/assets/img/mikanbot.png differ
diff --git a/src/components/ContactCard.tsx b/src/components/ContactCard.tsx
new file mode 100644
index 0000000..42683d5
--- /dev/null
+++ b/src/components/ContactCard.tsx
@@ -0,0 +1,85 @@
+import { LucideIcon } from "lucide-react";
+import {
+ Card,
+ CardContent,
+ CardHeader,
+ CardTitle,
+ CardFooter,
+} from "@/components/ui/card";
+import { Button } from "@/components/ui/button";
+import Link from "next/link";
+
+export interface IContactCardProps {
+ icon: LucideIcon;
+ title: string;
+ description?: string;
+ contactItems: IContactItem[];
+ actionButton?: {
+ href: string;
+ label: string;
+ };
+}
+
+export interface IContactItem {
+ icon: LucideIcon;
+ text: string;
+ title?: string;
+ href?: string;
+}
+
+export function ContactCard({
+ icon: Icon,
+ title,
+ description,
+ contactItems,
+ actionButton,
+}: IContactCardProps) {
+ return (
+
+
+
+
+
+
+
+
+ {title}
+
+ {description && (
+
+ {description}
+
+ )}
+
+ {contactItems.map((item, index) => (
+
+
+ {item.href ? (
+
+ {item.text}
+
+ ) : (
+ {item.text}
+ )}
+
+ ))}
+
+
+ {actionButton && (
+
+
+
+
+
+ )}
+
+ );
+}
diff --git a/src/components/CustomCursor.tsx b/src/components/CustomCursor.tsx
index c70ef6d..c6226b2 100644
--- a/src/components/CustomCursor.tsx
+++ b/src/components/CustomCursor.tsx
@@ -1,6 +1,6 @@
"use client";
import { useEffect, useRef } from "react";
-import Mikan from "@/assets/img/mikan.png";
+import MikanCursor from "@/assets/img/MiknCursor.png";
import Image from "next/image";
export default function CustomCursor() {
@@ -49,9 +49,9 @@ export default function CustomCursor() {
}}
>
{description}
+ {tags && (
+
+ {tags.map((tag) => (
+
+ {tag}
+
+ ))}
+
+ )}
@@ -62,7 +76,7 @@ export function OSSProductCard({
variant="ghost"
className="w-full justify-start gap-2 h-auto py-2 hover:bg-primary/10 hover:text-primary"
>
-
+
{t("viewRepo")}
diff --git a/src/components/SettingsController.tsx b/src/components/SettingsController.tsx
index 501dc67..d4ad833 100644
--- a/src/components/SettingsController.tsx
+++ b/src/components/SettingsController.tsx
@@ -80,7 +80,7 @@ export default function SettingsController({ children }: AccButtonProps) {
disabled={selectedToy === "custom"}
onClick={() => setSelectedToy("custom")}
>
- Custom Cursor
+ mamomamo
{t("title")}
-{t("mail")}
-hello@mikn.dev
-billing@mikn.dev
-abuse@mikn.dev
-{t("phone")}
-+81 090-9276-3628
-{t("discord")}
-{t("phone-disclaimer")}
++ {t(`${section.key}.description`)} +
++ {description} +
+ )} +