Github Widget
Rendered Component
Loading component...
Packages
npm install framer-motion
npm install @fortawesome/react-fontawesome
npm install @fortawesome/free-solid-svg-icons
npm install @fortawesome/free-brands-svg-icons
yarn add framer-motion
yarn add @fortawesome/react-fontawesome
yarn add @fortawesome/free-solid-svg-icons
yarn add @fortawesome/free-brands-svg-icons
Code
import React, { useState, useEffect } from 'react';
import { motion } from 'framer-motion';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
faGithub,
faStar,
faCodeBranch,
faSpinner,
} from '@fortawesome/free-solid-svg-icons';
import { faGithubAlt } from '@fortawesome/free-brands-svg-icons';
const GitHubStats = ({ username }) => {
const [userData, setUserData] = useState(null);
const [repoData, setRepoData] = useState(null);
const [loading, setLoading] = useState({ user: true, repo: true });
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const userResponse = await fetch(
`https://api.github.com/users/${username}`
);
if (!userResponse.ok) {
throw new Error('Failed to fetch user data');
}
const userData = await userResponse.json();
setUserData(userData);
setLoading((prev) => ({ ...prev, user: false }));
const reposResponse = await fetch(
`https://api.github.com/users/${username}/repos?sort=stars&per_page=100`
);
if (!reposResponse.ok) {
throw new Error('Failed to fetch repo data');
}
const reposData = await reposResponse.json();
const pm2Dashboard = reposData.find(
(repo) => repo.name.toLowerCase() === 'pm2-ui'
);
setRepoData(pm2Dashboard);
setLoading((prev) => ({ ...prev, repo: false }));
} catch (error) {
console.error('Error fetching GitHub data:', error);
setError(error.message);
setLoading({ user: false, repo: false });
}
};
fetchData();
}, [username]);
const SpinnerIcon = () => (
<FontAwesomeIcon icon={faSpinner} spin className='text-blue-400' />
);
return (
<div className='flex bg-zinc-900 rounded-xl'>
<div className='flex flex-col items-center justify-center w-1/2 px-4'>
<FontAwesomeIcon
icon={faGithubAlt}
className='mr-2 w-6 h-6 text-zinc-200'
/>
<h2 className='text-2xl text-white font-semibold mb-2 flex items-center'>
Github Stats
</h2>
</div>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
className='bg-zinc-800 w-full p-4 rounded-xl shadow-lg text-zinc-200'
>
{error ? (
<div className='text-red-500'>Error: {error}</div>
) : (
<div className=' p-3 rounded flex justify-around gap-6'>
<div>
<p className='text-gray-400'>Followers</p>
<p className='text-2xl font-bold'>
{loading.user ? (
<FontAwesomeIcon icon={faSpinner} className='animate-spin' />
) : (
userData?.followers
)}
</p>
</div>
<div>
{loading.repo ? (
<FontAwesomeIcon icon={faSpinner} className='animate-spin' />
) : (
<a
href={repoData?.html_url}
target='_blank'
rel='noopener noreferrer'
className='hover:text-blue-400 text-xl font-bold'
>
{repoData?.name}
</a>
)}
<div className='flex items-center mt-1 text-sm text-gray-400'>
<span className='mr-3'>
<FontAwesomeIcon icon={faStar} className='mr-1 w-5 h-5' />
{loading.repo ? (
<FontAwesomeIcon
icon={faSpinner}
className='animate-spin'
/>
) : (
repoData?.stargazers_count
)}
</span>
<span>
<FontAwesomeIcon
icon={faCodeBranch}
className='mr-1 w-5 h-5'
/>
{loading.repo ? (
<FontAwesomeIcon
icon={faSpinner}
className='animate-spin'
/>
) : (
repoData?.forks_count
)}
</span>
</div>
</div>
</div>
)}
</motion.div>
</div>
);
};
export default GitHubStats;
Details
The Terminal Window component is a fun and interactive way to display text-based information. It emulates the look and feel of a retro terminal interface, complete with a blinking cursor and customizable themes.
Usage
Import the TerminalWindow component and provide it with the necessary text content and styling options.
Examples
- Homepage weather display
- Travel app destination weather
- Smart home dashboard weather widget