Skip to content
Open
50 changes: 50 additions & 0 deletions components/PromptInstall.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Image from "next/image";
import React from "react";
import { GrDownload } from "react-icons/gr";

export default function PromptInstall({
fun,
open,
close,
}: {
fun: () => void;
open: boolean;
close: () => void;
}) {
return open ? (
<div className="fixed inset-0 w-dvw h-dvh bg-black/40 backdrop-blur flex">
<div className="absolute inset-0 w-full h-full z-0" onClick={close}></div>
<div
className={`mt-auto mx-auto bg-white rounded-t-3xl p-6 pb-8 w-[min(600px,100%)] z-10 relative${
open ? " am-ami-animate-to-top" : ""
}`}
>
<Image
className="object-contain absolute h-8 w-8 top-5 right-5 cursor-pointer"
alt="selected"
src={`/assets/images/icons/close.svg`}
width={32}
height={32}
onClick={close}
/>
<h1 className="font-bold text-xl">Install Our App</h1>
<div className="flex items-center justify-between gap-6 pt-5 pr-2">
<p className={``}>
Get our App experience optimized for your device.
</p>
<button className="px-4 py-3 text-xl font-semibold bg-[#88A6FA] rounded-lg flex items-center gap-3 text-white">
<Image
src="/assets/images/icons/download.svg"
alt="download"
width={20}
height={20}
/>{" "}
Install
</button>
</div>
</div>
</div>
) : (
<></>
);
}
18 changes: 12 additions & 6 deletions layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
"use client";
import { HeaderProps } from "@/config";
import { chain } from "@/constant";
import { useChain } from "@cosmos-kit/react";
import Image from "next/image";
import Link from "next/link";
import { useEffect, useState } from "react";

export default function Header({
profileName,
setIsLogin,
isLogin,
}: HeaderProps) {
export default function Header() {
const { connect, address } = useChain(chain);
const [isLogin, setIsLogin] = useState(false);

useEffect(() => {
const loginStat = localStorage.getItem("loggedIn");
loginStat === "yes" ? setIsLogin(true) : setIsLogin(false);
}, []);

useEffect(() => {
localStorage.loggedIn = isLogin ? "yes" : "no";
}, [isLogin]);

const handleProfileIconClick = async () => {
if (!address) {
Expand Down
20 changes: 16 additions & 4 deletions pages/404.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import Image from "next/image";
import Link from "next/link";

export default function NotFound() {
return (
<div>
<h2>Not Found</h2>
<p>Could not find requested resource</p>
<Link href="/">Return Home</Link>
<div className="h-dvh flex flex-col items-center justify-center gap-4 w-[min(600px,100%)] mx-auto py-6 px-4">
<Image
src={`/assets/images/404.svg`}
alt={"404 Page Not found illustration"}
width={400}
height={400}
className="object-contain w-[min(250px,100%)]"
/>
<h2 className="text-xl">Page Not Found</h2>
<Link
href="/"
className="px-4 py-2 text-md font-semibold bg-[#88A6FA] rounded-lg flex items-center gap-3 text-white"
>
Go To Home
</Link>
</div>
);
}
30 changes: 22 additions & 8 deletions pages/500.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
import Image from "next/image";
import Link from "next/link";

// pages/error.tsx
export default function ErrorPage() {
return (
<div>
<h1>Error</h1>
<p>The requested profile does not exist.</p>
</div>
);
}

return (
<div className="h-dvh flex flex-col items-center justify-center gap-4 w-[min(600px,100%)] mx-auto py-6 px-4">
<Image
src={`/assets/images/error.svg`}
alt={"500 An Error Occurred illustration"}
width={400}
height={400}
className="object-contain w-[min(250px,100%)]"
/>
<h2 className="text-xl">An Error Occurred</h2>
<Link
href="/"
className="px-4 py-2 text-md font-semibold bg-[#88A6FA] rounded-lg flex items-center gap-3 text-white"
>
Go To Home
</Link>
</div>
);
}
11 changes: 5 additions & 6 deletions pages/[id]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client";
import Loading from "@/components/Loading";
import { defaultChainName } from "@/config";
import Header from "@/layout/Header";
import { isValidReferrer, showToastMessage, updateMyAmiList } from "@/utils";
import ProfilePrivateView from "@/views/profile/ProfilePrivateView";
import ProfilePublicView from "@/views/profile/ProfilePublicView";
Expand All @@ -19,6 +18,11 @@ export default function Profile() {
const [isMyProfile, setIsMyProfile] = useState(false);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
const loginStat = localStorage.getItem("loggedIn");
loginStat === "yes" ? setIsLogin(true) : setIsLogin(false);
}, []);

useEffect(() => {
const fetchData = async () => {
// Redirect to error page if PROFILE_NAME is not available
Expand Down Expand Up @@ -150,11 +154,6 @@ export default function Profile() {

return (
<>
<Header
profileName={PROFILE_NAME}
setIsLogin={setIsLogin}
isLogin={isMyProfile}
/>
<main className="am-ami-container-sm h-[calc(100dvh-97.02px)] overflow-y-hidden scroll-smooth snap-mandatory snap-y relative">
{isMyProfile ? (
<>
Expand Down
42 changes: 42 additions & 0 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { SignerOptions, wallets } from "cosmos-kit";
import Head from "next/head";
import { ToastContainer } from "react-toastify";
import { aminoTypes, registry } from "../config/defaults";
import PromptInstall from "@/components/PromptInstall";
import Header from "@/layout/Header";

const queryClient = new QueryClient({
defaultOptions: {
Expand All @@ -38,6 +40,8 @@ function CreateCosmosApp({ Component, pageProps }: AppProps) {

// State to manage loading screen
const [isLoading, setIsLoading] = useState(false);
const [deferredPrompt, setDeferredPrompt] = useState<Event | null>(null);
const [isInstallable, setIsInstallable] = useState(false);

const signerOptions: SignerOptions = {
// @ts-ignore
Expand Down Expand Up @@ -94,6 +98,38 @@ function CreateCosmosApp({ Component, pageProps }: AppProps) {
};
}, [router]);

// Checking if Install Prompt should be opened (only on load)
useEffect(() => {
const handleBeforeInstallPrompt = (e: Event) => {
e.preventDefault();
setDeferredPrompt(e);
setIsInstallable(true);
};
window.addEventListener("beforeinstallprompt", handleBeforeInstallPrompt);
return () => {
window.removeEventListener(
"beforeinstallprompt",
handleBeforeInstallPrompt
);
};
}, []);

const handleInstall = async () => {
if (deferredPrompt) {
const promptEvent = deferredPrompt as any;
promptEvent.prompt();
const choiceResult = await promptEvent.userChoice;
if (choiceResult.outcome === "accepted") {
console.log("PWA installation accepted");
} else {
console.log("PWA installation dismissed");
}

setDeferredPrompt(null);
setIsInstallable(false);
}
};

return (
<>
<Head>
Expand Down Expand Up @@ -188,7 +224,13 @@ function CreateCosmosApp({ Component, pageProps }: AppProps) {
minHeight="100dvh"
backgroundColor={useColorModeValue("#ffffff", "#ffffff")}
>
<Header />
<Component {...pageProps} />
<PromptInstall
fun={handleInstall}
open={isInstallable}
close={() => setIsInstallable(false)}
/>
{isLoading && <Loading />}
</Box>
</QueryClientProvider>
Expand Down
2 changes: 1 addition & 1 deletion pages/search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export default function Home() {
}, [address]);

return (
<main className="flex h-[100dvh] flex-col items-center justify-center font-inter p-6 am-ami-container-sm">
<main className="flex h-[calc(100dvh-97.02px)] flex-col items-center justify-center font-inter p-6 am-ami-container-sm">
<div className="flex items-center justify-center w-[min(320px,100%)] mx-auto relative">
<div className="flex aspect-square w-[50px] rounded-[50%] scale-[1.1] origin-left">
<Image
Expand Down
1 change: 1 addition & 0 deletions public/assets/images/404.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions public/assets/images/error.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions public/assets/images/icons/download.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.