Skip to content

Commit

Permalink
🥳 Improve Greeting and Tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
mskian committed Aug 8, 2024
1 parent aac3d14 commit 488ec5f
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 32 deletions.
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,35 @@ A special 🇮🇳 Happy Independence Day greeting for your friends and Family M
- Vite.js
- Typescript
- Tailwind CSS
- Free Hosting on Netlify : **<https://indiawish.netlify.app/>**
- 🇮🇳 CSS Flag
- Hosting at Netlify : **<https://indiawish.netlify.app/>**

## Setup and Usage

- Clone or Download the Repo

```sh
git clone https://github.com/mskian/independence-day-app
cd independence-day-app
```

- Install dependencies

```sh
pnpm install
```

- Test

```sh
pnpm dev
```

- Build the App

```sh
pnpm build
```

## LICENSE

Expand Down
7 changes: 5 additions & 2 deletions src/components/Greeting.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState } from 'preact/hooks';
import slugify from 'slugify';
import IndianFlag from './IndianFlag';

const Greeting = () => {
const [name, setName] = useState<string>('');
Expand Down Expand Up @@ -48,7 +49,8 @@ const Greeting = () => {
<div class="flex flex-col items-center justify-center min-h-screen bg-gradient-to-b from-orange-500 via-white to-green-600">
<div class="flex flex-col items-center justify-center max-w-md w-full p-6">
<div class="bg-gradient-to-r from-white via-gray-100 to-gray-200 p-6 rounded-lg shadow-lg w-full text-center">
<p class="text-6xl mb-6">🇮🇳</p>
<IndianFlag />
<br />
<h2 class="text-3xl font-bold text-gray-800 mb-4">Independence Day Greeting</h2>
<p class="text-lg text-gray-700 mb-6">Enter your name to receive a personalized greeting</p>
<form onSubmit={handleSubmit} class="bg-gradient-to-r from-orange-500 to-green-800 text-white p-8 rounded-lg shadow-md w-full">
Expand All @@ -72,7 +74,8 @@ const Greeting = () => {
</button>
</form>
<div class="mt-10">
<p class="text-sm text-gray-700 mb-6">Built Using Preact and Vite.js<br /><a href="https://github.com/mskian/independence-day-app" target="_blank" rel="nofollow noopener" class="text-rose-900 hover:underline">
<hr class="border-t-2 border-gray-800 my-8" />
<p class="text-sm text-gray-700 mb-6">Built Using 🥳 Preact and Vite 🔥<br />🥤 <a href="https://github.com/mskian/independence-day-app" target="_blank" rel="nofollow noopener" class="text-rose-900 hover:underline">
View on GitHub</a>
</p>
</div>
Expand Down
98 changes: 70 additions & 28 deletions src/components/GreetingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { JSX } from 'preact';
import DOMPurify from 'dompurify';
import slugify from 'slugify';
import { useEffect, useState } from 'preact/hooks';
import IndianFlag from './IndianFlag';

interface GreetingPageProps {
name?: string;
Expand Down Expand Up @@ -47,16 +48,27 @@ const Snackbar = ({ message, onClose }: { message: string; onClose: () => void }
);

const GreetingPage = (props: GreetingPageProps & JSX.IntrinsicElements['div']) => {
const [loading, setLoading] = useState(true);
const [snackbarMessage, setSnackbarMessage] = useState<string | null>(null);
const [toggleState, setToggleState] = useState(false);
const { name } = props;
const sanitizedName = sanitizeName(name || '');
const currentTime = getFormattedTime();
const currentUrl = window.location.href;

useEffect(() => {
const savedToggleState = localStorage.getItem('toggleState');
if (savedToggleState !== null) {
setToggleState(JSON.parse(savedToggleState));
}

setTimeout(() => {
setLoading(false);
}, 2000);

const metaTitle = `${sanitizedName ? `${sanitizedName}` : ''} - Independence Day Greeting 🇮🇳`;
const metaDescription = `Wishing you a very Happy Independence Day From ${sanitizedName ? `${sanitizedName}` : ''} - Check out your personalized greeting page.`;

document.title = metaTitle;

let metaDescriptionTag = document.querySelector('meta[name="description"]') as HTMLMetaElement;
Expand All @@ -80,7 +92,7 @@ const GreetingPage = (props: GreetingPageProps & JSX.IntrinsicElements['div']) =
}

return () => {
document.title = 'Default Title';
document.title = 'Independence Day Greeting 🇮🇳';
const metaDescriptionTag = document.querySelector('meta[name="description"]') as HTMLMetaElement;
if (metaDescriptionTag) metaDescriptionTag.content = '';
const linkCanonicalTag = document.querySelector('link[rel="canonical"]') as HTMLLinkElement;
Expand All @@ -95,7 +107,12 @@ const GreetingPage = (props: GreetingPageProps & JSX.IntrinsicElements['div']) =
};

const redirectToHome = () => {
window.location.href = '/';
try {
window.location.href = '/';
} catch (error) {
console.error('Error redirecting to home:', error);
setSnackbarMessage('Failed to redirect. Please try again.');
}
};

useEffect(() => {
Expand All @@ -108,36 +125,61 @@ const GreetingPage = (props: GreetingPageProps & JSX.IntrinsicElements['div']) =
return () => clearTimeout(timer);
}, [snackbarMessage]);

useEffect(() => {
localStorage.setItem('toggleState', JSON.stringify(toggleState));
}, [toggleState]);

return (
<div class="flex flex-col items-center justify-center min-h-screen bg-gradient-to-b from-orange-500 via-white to-green-600 p-4">
{loading ? (
<div class="flex items-center justify-center mb-8">
<div class="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-green-800"></div>
</div>
) : (
<>
<div class="chat-container mb-4">
<div class="chat-box">
<div class="chat-bubble right shadow-md focus:outline-none transition-transform duration-200 transform hover:scale-105">
{sanitizedName ? `${sanitizedName} 🇮🇳` : '🇮🇳 Your Name Here'}
<div class="chat-time">{currentTime}</div>
</div>
<div class="chat-bubble left shadow-md focus:outline-none transition-transform duration-200 transform hover:scale-105">
<p>Wishing you a very Happy Independence Day 🇮🇳</p>
<div class="chat-time">{currentTime}</div>
<IndianFlag />
<div class="chat-box">
<div class="chat-bubble right shadow-md focus:outline-none transition-transform duration-200 transform hover:scale-105">
{sanitizedName ? `${sanitizedName} 🇮🇳` : '🇮🇳 Your Name Here'}
<div class="chat-time">{currentTime}</div>
</div>
<div class="chat-bubble left shadow-md focus:outline-none transition-transform duration-200 transform hover:scale-105">
<p>Wishing you a very Happy Independence Day 🇮🇳</p>
<div class="chat-time">{currentTime}</div>
</div>
<div class="chat-bubble right shadow-md focus:outline-none transition-transform duration-200 transform hover:scale-105">
<p>Let us remember the sacrifices of our great leaders and honor their legacy by working towards a brighter future for our nation</p>
<div class="chat-time">{currentTime}</div>
</div>
<div class="chat-bubble left shadow-md focus:outline-none transition-transform duration-200 transform hover:scale-105">
<p>May the flag of India always fly high and may our country continue to grow stronger and more united</p>
<div class="chat-time">{currentTime}</div>
</div>
</div>
</div>
<div class="chat-bubble right shadow-md focus:outline-none transition-transform duration-200 transform hover:scale-105">
<p>Let us remember the sacrifices of our great leaders and honor their legacy by working towards a brighter future for our nation</p>
<div class="chat-time">{currentTime}</div>
<div class="mb-4">
<label class="flex items-center cursor-pointer">
<span class="mr-2 text-lg">{toggleState ? 'Hide Options' : 'Show Options'}</span>
<div class="relative">
<input type="checkbox" checked={toggleState} onChange={() => setToggleState(!toggleState)} class="sr-only" />
<div class={`block w-16 h-8 rounded-full ${toggleState ? 'bg-green-500' : 'bg-red-500'}`}></div>
<div class={`dot absolute left-1 top-1 bg-white w-6 h-6 rounded-full transition-transform ${toggleState ? 'transform translate-x-8' : ''}`}></div>
</div>
</label>
</div>
<div class="chat-bubble left shadow-md focus:outline-none transition-transform duration-200 transform hover:scale-105">
<p>May the flag of India always fly high and may our country continue to grow stronger and more united</p>
<div class="chat-time">{currentTime}</div>
</div>
</div>
</div>
<div class="bg-white p-6 rounded-lg shadow-md mb-6 w-full max-w-md flex justify-between items-center space-x-4">
<button onClick={copyToClipboard} class="bg-gradient-to-r from-blue-400 to-blue-600 text-white px-4 py-2 rounded-lg shadow-md hover:from-blue-500 hover:to-blue-700">
Copy URL
</button>
<button onClick={redirectToHome} class="bg-gradient-to-r from-green-400 to-green-600 text-white px-4 py-2 rounded-lg shadow-md hover:from-green-500 hover:to-green-700">
Create
</button>
</div>
{toggleState && (
<div class="bg-white p-6 rounded-lg shadow-md mb-6 w-full max-w-md flex justify-between items-center space-x-4">
<button onClick={copyToClipboard} class="bg-gradient-to-r from-blue-400 to-blue-600 text-white px-4 py-2 rounded-lg shadow-md hover:from-blue-500 hover:to-blue-700">
Copy URL
</button>
<button onClick={redirectToHome} class="bg-gradient-to-r from-green-400 to-green-600 text-white px-4 py-2 rounded-lg shadow-md hover:from-green-500 hover:to-green-700">
Create
</button>
</div>
)}
</>
)}
{snackbarMessage && (
<Snackbar
message={snackbarMessage}
Expand Down
30 changes: 30 additions & 0 deletions src/components/IndianFlag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const IndianFlag = () => {
return (
<div className="custom-flag-container">
<div className="custom-flag-pole"></div>
<div className="custom-flag">
<div className="wave"></div>
<div className="custom-stripe custom-stripe-orange"></div>
<div className="custom-stripe custom-stripe-white">
<div className="custom-ashoka-chakra">
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
</div>
</div>
<div className="custom-stripe custom-stripe-green"></div>
</div>
</div>
);
};

export default IndianFlag;
108 changes: 107 additions & 1 deletion src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,110 @@ html {
color: #888;
margin-top: 0.5rem;
text-align: right;
}
}
.custom-flag-container {
display: flex;
align-items: flex-start;
justify-content: center;
padding-top: 20px;
}

.custom-flag-pole {
width: 5px;
height: 100px;
background-color: #000;
border-radius: 2px;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
}

.custom-flag {
width: 96px;
height: 64px;
box-shadow: 0px 0px 90px 1px #989;
background-color: transparent;
position: relative;
}

.custom-stripe {
height: 21.33px;
display: flex;
align-items: center;
justify-content: center;
}

.custom-stripe-orange {
background-color: #FF9933;
}

.custom-stripe-white {
background-color: #FFFFFF;
position: relative;
}

.custom-stripe-green {
background-color: #138808;
}

.custom-ashoka-chakra {
height: 22px;
width: 22px;
border: 1px solid darkblue;
border-radius: 50%;
position: relative;
margin: 0 auto;
}

.custom-ashoka-chakra .line {
height: 100%;
width: 1px;
display: inline-block;
position: absolute;
left: 50%;
background: darkblue;
}

.custom-ashoka-chakra .line:nth-child(1) { transform: rotate(15deg); }
.custom-ashoka-chakra .line:nth-child(2) { transform: rotate(30deg); }
.custom-ashoka-chakra .line:nth-child(3) { transform: rotate(45deg); }
.custom-ashoka-chakra .line:nth-child(4) { transform: rotate(60deg); }
.custom-ashoka-chakra .line:nth-child(5) { transform: rotate(75deg); }
.custom-ashoka-chakra .line:nth-child(6) { transform: rotate(90deg); }
.custom-ashoka-chakra .line:nth-child(7) { transform: rotate(105deg); }
.custom-ashoka-chakra .line:nth-child(8) { transform: rotate(120deg); }
.custom-ashoka-chakra .line:nth-child(9) { transform: rotate(135deg); }
.custom-ashoka-chakra .line:nth-child(10) { transform: rotate(150deg); }
.custom-ashoka-chakra .line:nth-child(11) { transform: rotate(165deg); }
.custom-ashoka-chakra .line:nth-child(12) { transform: rotate(180deg); }

@keyframes custom-wave {
0% { transform: rotate(0deg); }
25% { transform: rotate(4deg); }
50% { transform: rotate(-4deg); }
75% { transform: rotate(4deg); }
100% { transform: rotate(0deg); }
}

.wave {
position: absolute;
height: 100%;
width: 100%;
background-image: linear-gradient(
128deg, rgba(89, 72, 21, 0) 39%,
rgba(250, 245, 245, 0.8474025974025974)
46%, rgba(89, 72, 21, 0) 53%);
animation-name: wavy;
animation-duration: 10s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}

@keyframes wavy {
0% {
background-position: -400px 0px,
-400px 0px, -400px 0px, -400px 0px;
}
100% {
background-position: 800px 0px,
800px 0px, 800px 0px, 800px 0px;
}
}

0 comments on commit 488ec5f

Please sign in to comment.