commit
8f413562e9
93
README.md
93
README.md
@ -43,7 +43,7 @@
|
|||||||
**Features:**
|
**Features:**
|
||||||
|
|
||||||
✓ [Easy to Setup](#-installation--setup)
|
✓ [Easy to Setup](#-installation--setup)
|
||||||
✓ [33 Themes](#themes)
|
✓ [37 Themes](#themes)
|
||||||
✓ [Google Analytics](#google-analytics)
|
✓ [Google Analytics](#google-analytics)
|
||||||
✓ [Hotjar](#hotjar)
|
✓ [Hotjar](#hotjar)
|
||||||
✓ [SEO](#seo)
|
✓ [SEO](#seo)
|
||||||
@ -202,11 +202,7 @@ const CONFIG = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
seo: {
|
seo: { title: 'Portfolio of Ariful Alam', description: '', imageURL: '' },
|
||||||
title: 'Portfolio of Ariful Alam',
|
|
||||||
description: '',
|
|
||||||
imageURL: '',
|
|
||||||
},
|
|
||||||
social: {
|
social: {
|
||||||
linkedin: 'ariful-alam',
|
linkedin: 'ariful-alam',
|
||||||
x: 'arif_szn',
|
x: 'arif_szn',
|
||||||
@ -317,10 +313,7 @@ const CONFIG = {
|
|||||||
id: '', // GA3 tracking id/GA4 tag id UA-XXXXXXXXX-X | G-XXXXXXXXXX
|
id: '', // GA3 tracking id/GA4 tag id UA-XXXXXXXXX-X | G-XXXXXXXXXX
|
||||||
},
|
},
|
||||||
// Track visitor interaction and behavior. https://www.hotjar.com
|
// Track visitor interaction and behavior. https://www.hotjar.com
|
||||||
hotjar: {
|
hotjar: { id: '', snippetVersion: 6 },
|
||||||
id: '',
|
|
||||||
snippetVersion: 6,
|
|
||||||
},
|
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
defaultTheme: 'nord',
|
defaultTheme: 'nord',
|
||||||
|
|
||||||
@ -369,19 +362,11 @@ const CONFIG = {
|
|||||||
'dim',
|
'dim',
|
||||||
'nord',
|
'nord',
|
||||||
'sunset',
|
'sunset',
|
||||||
|
'caramellatte',
|
||||||
|
'abyss',
|
||||||
|
'silk',
|
||||||
'procyon',
|
'procyon',
|
||||||
],
|
],
|
||||||
|
|
||||||
// Custom theme, applied to `procyon` theme
|
|
||||||
customTheme: {
|
|
||||||
primary: '#fc055b',
|
|
||||||
secondary: '#219aaf',
|
|
||||||
accent: '#e8d03a',
|
|
||||||
neutral: '#2A2730',
|
|
||||||
'base-100': '#E3E3ED',
|
|
||||||
'--rounded-box': '3rem',
|
|
||||||
'--rounded-btn': '3rem',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Optional Footer. Supports plain text or HTML.
|
// Optional Footer. Supports plain text or HTML.
|
||||||
@ -399,7 +384,7 @@ export default CONFIG;
|
|||||||
|
|
||||||
### Themes
|
### Themes
|
||||||
|
|
||||||
There are 33 themes available that can be selected from the dropdown.
|
There are 37 themes available that can be selected from the dropdown.
|
||||||
|
|
||||||
The default theme can be specified.
|
The default theme can be specified.
|
||||||
|
|
||||||
@ -418,34 +403,23 @@ const CONFIG = {
|
|||||||
<img src="https://github.com/arifszn/gitprofile/assets/45073703/91a2d9e6-67e5-47b4-9752-1881ac0f907f" alt="Theme Dropdown" width="50%">
|
<img src="https://github.com/arifszn/gitprofile/assets/45073703/91a2d9e6-67e5-47b4-9752-1881ac0f907f" alt="Theme Dropdown" width="50%">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
You can create your own custom theme by modifying these values. Theme `procyon` will have the custom styles.
|
You can create your own custom theme by modifying the CSS variables in `src/assets/index.css`. Theme `procyon` is defined as a custom theme.
|
||||||
|
|
||||||
```ts
|
```css
|
||||||
// gitprofile.config.ts
|
/* src/assets/index.css */
|
||||||
const CONFIG = {
|
@plugin "daisyui/theme" {
|
||||||
/**
|
name: 'procyon';
|
||||||
* Defines the custom theme colors and styles for the application.
|
color-scheme: light;
|
||||||
* The theme includes the following properties:
|
|
||||||
* - `primary`: The primary color used throughout the application.
|
--color-base-100: #e3e3ed;
|
||||||
* - `secondary`: The secondary color used for accents and highlights.
|
--color-base-200: #d1d1db;
|
||||||
* - `accent`: The accent color used for special elements.
|
--color-base-300: #bfbfc9;
|
||||||
* - `neutral`: The neutral color used for backgrounds and text.
|
--color-base-content: #2a2730;
|
||||||
* - `base-100`: The base background color.
|
--color-primary: #fc055b;
|
||||||
* - `--rounded-box`: The border radius for boxes and containers.
|
--color-primary-content: #ffffff;
|
||||||
* - `--rounded-btn`: The border radius for buttons.
|
--color-secondary: #219aaf;
|
||||||
*/
|
--color-secondary-content: #ffffff;
|
||||||
themeConfig: {
|
}
|
||||||
customTheme: {
|
|
||||||
primary: '#fc055b',
|
|
||||||
secondary: '#219aaf',
|
|
||||||
accent: '#e8d03a',
|
|
||||||
neutral: '#2A2730',
|
|
||||||
'base-100': '#E3E3ED',
|
|
||||||
'--rounded-box': '3rem',
|
|
||||||
'--rounded-btn': '3rem',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Google Analytics
|
### Google Analytics
|
||||||
@ -456,9 +430,7 @@ const CONFIG = {
|
|||||||
// gitprofile.config.ts
|
// gitprofile.config.ts
|
||||||
const CONFIG = {
|
const CONFIG = {
|
||||||
// ...
|
// ...
|
||||||
googleAnalytics: {
|
googleAnalytics: { id: 'G-XXXXXXXXX' },
|
||||||
id: 'G-XXXXXXXXX',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -472,10 +444,7 @@ Besides tracking visitors, it will track `click events` on projects and blog pos
|
|||||||
// gitprofile.config.ts
|
// gitprofile.config.ts
|
||||||
const CONFIG = {
|
const CONFIG = {
|
||||||
// ...
|
// ...
|
||||||
hotjar: {
|
hotjar: { id: '', snippetVersion: 6 },
|
||||||
id: '',
|
|
||||||
snippetVersion: 6,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -487,11 +456,7 @@ You can customize the meta tags for SEO in `seo`.
|
|||||||
// gitprofile.config.ts
|
// gitprofile.config.ts
|
||||||
const CONFIG = {
|
const CONFIG = {
|
||||||
// ...
|
// ...
|
||||||
seo: {
|
seo: { title: 'Portfolio of Ariful Alam', description: '', imageURL: '' },
|
||||||
title: 'Portfolio of Ariful Alam',
|
|
||||||
description: '',
|
|
||||||
imageURL: '',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -730,11 +695,7 @@ If you have [medium](https://medium.com) or [dev](https://dev.to) account, you c
|
|||||||
// gitprofile.config.ts
|
// gitprofile.config.ts
|
||||||
const CONFIG = {
|
const CONFIG = {
|
||||||
// ...
|
// ...
|
||||||
blog: {
|
blog: { source: 'dev', username: 'arifszn', limit: 5 },
|
||||||
source: 'dev',
|
|
||||||
username: 'arifszn',
|
|
||||||
limit: 5,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@ -51,11 +51,7 @@ const CONFIG = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
seo: {
|
seo: { title: 'Portfolio of Ariful Alam', description: '', imageURL: '' },
|
||||||
title: 'Portfolio of Ariful Alam',
|
|
||||||
description: '',
|
|
||||||
imageURL: '',
|
|
||||||
},
|
|
||||||
social: {
|
social: {
|
||||||
linkedin: 'ariful-alam',
|
linkedin: 'ariful-alam',
|
||||||
x: 'arif_szn',
|
x: 'arif_szn',
|
||||||
@ -166,10 +162,7 @@ const CONFIG = {
|
|||||||
id: '', // GA3 tracking id/GA4 tag id UA-XXXXXXXXX-X | G-XXXXXXXXXX
|
id: '', // GA3 tracking id/GA4 tag id UA-XXXXXXXXX-X | G-XXXXXXXXXX
|
||||||
},
|
},
|
||||||
// Track visitor interaction and behavior. https://www.hotjar.com
|
// Track visitor interaction and behavior. https://www.hotjar.com
|
||||||
hotjar: {
|
hotjar: { id: '', snippetVersion: 6 },
|
||||||
id: '',
|
|
||||||
snippetVersion: 6,
|
|
||||||
},
|
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
defaultTheme: 'lofi',
|
defaultTheme: 'lofi',
|
||||||
|
|
||||||
@ -218,19 +211,11 @@ const CONFIG = {
|
|||||||
'dim',
|
'dim',
|
||||||
'nord',
|
'nord',
|
||||||
'sunset',
|
'sunset',
|
||||||
|
'caramellatte',
|
||||||
|
'abyss',
|
||||||
|
'silk',
|
||||||
'procyon',
|
'procyon',
|
||||||
],
|
],
|
||||||
|
|
||||||
// Custom theme, applied to `procyon` theme
|
|
||||||
customTheme: {
|
|
||||||
primary: '#fc055b',
|
|
||||||
secondary: '#219aaf',
|
|
||||||
accent: '#e8d03a',
|
|
||||||
neutral: '#2A2730',
|
|
||||||
'base-100': '#E3E3ED',
|
|
||||||
'--rounded-box': '3rem',
|
|
||||||
'--rounded-btn': '3rem',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Optional Footer. Supports plain text or HTML.
|
// Optional Footer. Supports plain text or HTML.
|
||||||
|
|||||||
42
global.d.ts
vendored
42
global.d.ts
vendored
@ -284,43 +284,6 @@ interface Blog {
|
|||||||
limit?: number;
|
limit?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CustomTheme {
|
|
||||||
/**
|
|
||||||
* Primary color
|
|
||||||
*/
|
|
||||||
primary?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Secondary color
|
|
||||||
*/
|
|
||||||
secondary?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accent color
|
|
||||||
*/
|
|
||||||
accent?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Neutral color
|
|
||||||
*/
|
|
||||||
neutral?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base color of page
|
|
||||||
*/
|
|
||||||
'base-100'?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Border radius of rounded-box
|
|
||||||
*/
|
|
||||||
'--rounded-box'?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Border radius of rounded-btn
|
|
||||||
*/
|
|
||||||
'--rounded-btn'?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ThemeConfig {
|
interface ThemeConfig {
|
||||||
/**
|
/**
|
||||||
* Default theme
|
* Default theme
|
||||||
@ -346,11 +309,6 @@ interface ThemeConfig {
|
|||||||
* Available themes
|
* Available themes
|
||||||
*/
|
*/
|
||||||
themes?: Array<string>;
|
themes?: Array<string>;
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom theme
|
|
||||||
*/
|
|
||||||
customTheme?: CustomTheme;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Config {
|
interface Config {
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
<meta name="twitter:title" content="<%- metaTitle %>" />
|
<meta name="twitter:title" content="<%- metaTitle %>" />
|
||||||
<meta name="twitter:description" content="<%- metaDescription %>" />
|
<meta name="twitter:description" content="<%- metaDescription %>" />
|
||||||
<meta name="twitter:image" content="<%- metaImageURL %>" />
|
<meta name="twitter:image" content="<%- metaImageURL %>" />
|
||||||
|
<%- googleAnalyticsScript %>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
1567
package-lock.json
generated
1567
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
21
package.json
21
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@arifszn/gitprofile",
|
"name": "@arifszn/gitprofile",
|
||||||
"description": "Create an automatic portfolio based on GitHub profile",
|
"description": "Create an automatic portfolio based on GitHub profile",
|
||||||
"version": "3.1.0",
|
"version": "4.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "arifszn",
|
"author": "arifszn",
|
||||||
@ -22,31 +22,30 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^18.3.1",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "^19.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@arifszn/blog-js": "^2.0.6",
|
"@arifszn/blog-js": "^2.0.6",
|
||||||
"@types/react": "^18.3.3",
|
"@tailwindcss/postcss": "^4.1.11",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react": "^19.1.8",
|
||||||
|
"@types/react-dom": "^19.1.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.8.0",
|
"@typescript-eslint/eslint-plugin": "^7.8.0",
|
||||||
"@typescript-eslint/parser": "^7.3.1",
|
"@typescript-eslint/parser": "^7.3.1",
|
||||||
"@vitejs/plugin-react": "^4.4.1",
|
"@vitejs/plugin-react": "^4.4.1",
|
||||||
"autoprefixer": "^10.4.20",
|
|
||||||
"axios": "^1.10.0",
|
"axios": "^1.10.0",
|
||||||
"daisyui": "^4.11.1",
|
"daisyui": "^5.0.43",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^10.1.5",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-react-hooks": "^5.1.0",
|
"eslint-plugin-react-hooks": "^5.1.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.20",
|
"eslint-plugin-react-refresh": "^0.4.20",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"prettier": "^3.3.2",
|
"prettier": "^3.6.2",
|
||||||
"react-helmet-async": "^2.0.5",
|
|
||||||
"react-hotjar": "^6.3.1",
|
"react-hotjar": "^6.3.1",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^4.1.11",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vail": "^1.0.3",
|
"vail": "^1.0.3",
|
||||||
"vite": "^7.0.2",
|
"vite": "^7.0.2",
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
export default {
|
export default {
|
||||||
plugins: {
|
plugins: {
|
||||||
tailwindcss: {},
|
'@tailwindcss/postcss': {},
|
||||||
autoprefixer: {},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,55 @@
|
|||||||
@tailwind base;
|
@import 'tailwindcss';
|
||||||
@tailwind components;
|
@plugin "daisyui" {
|
||||||
@tailwind utilities;
|
themes:
|
||||||
|
'light', 'dark', 'cupcake', 'bumblebee', 'emerald', 'corporate',
|
||||||
|
'synthwave', 'retro', 'cyberpunk', 'valentine', 'halloween', 'garden',
|
||||||
|
'forest', 'aqua', 'lofi', 'pastel', 'fantasy', 'wireframe', 'black',
|
||||||
|
'luxury', 'dracula', 'cmyk', 'autumn', 'business', 'acid', 'lemonade',
|
||||||
|
'night', 'coffee', 'winter', 'dim', 'nord', 'sunset', 'caramellatte',
|
||||||
|
'abyss', 'silk', 'procyon';
|
||||||
|
}
|
||||||
|
|
||||||
|
@plugin "daisyui/theme" {
|
||||||
|
name: 'procyon';
|
||||||
|
color-scheme: light;
|
||||||
|
|
||||||
|
--color-base-100: #e3e3ed;
|
||||||
|
--color-base-200: #d1d1db;
|
||||||
|
--color-base-300: #bfbfc9;
|
||||||
|
--color-base-content: #2a2730;
|
||||||
|
--color-primary: #fc055b;
|
||||||
|
--color-primary-content: #ffffff;
|
||||||
|
--color-secondary: #219aaf;
|
||||||
|
--color-secondary-content: #ffffff;
|
||||||
|
--color-accent: #e8d03a;
|
||||||
|
--color-accent-content: #2a2730;
|
||||||
|
--color-neutral: #2a2730;
|
||||||
|
--color-neutral-content: #ffffff;
|
||||||
|
--color-info: #219aaf;
|
||||||
|
--color-info-content: #ffffff;
|
||||||
|
--color-success: #16a34a;
|
||||||
|
--color-success-content: #ffffff;
|
||||||
|
--color-warning: #e8d03a;
|
||||||
|
--color-warning-content: #2a2730;
|
||||||
|
--color-error: #dc2626;
|
||||||
|
--color-error-content: #ffffff;
|
||||||
|
|
||||||
|
/* border radius */
|
||||||
|
--radius-selector: 3rem;
|
||||||
|
--radius-field: 3rem;
|
||||||
|
--radius-box: 3rem;
|
||||||
|
|
||||||
|
/* base sizes */
|
||||||
|
--size-selector: 0.25rem;
|
||||||
|
--size-field: 0.25rem;
|
||||||
|
|
||||||
|
/* border size */
|
||||||
|
--border: 1px;
|
||||||
|
|
||||||
|
/* effects */
|
||||||
|
--depth: 1;
|
||||||
|
--noise: 0;
|
||||||
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
@ -40,10 +89,6 @@ code {
|
|||||||
source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-base-content-important {
|
|
||||||
color: hsla(var(--bc) / var(--tw-text-opacity)) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
vertical-align: unset;
|
vertical-align: unset;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,9 +23,9 @@ const AvatarCard: React.FC<AvatarCardProps> = ({
|
|||||||
loading,
|
loading,
|
||||||
avatarRing,
|
avatarRing,
|
||||||
resumeFileUrl,
|
resumeFileUrl,
|
||||||
}): JSX.Element => {
|
}): React.JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div className="card shadow-lg compact bg-base-100">
|
<div className="card shadow-lg card-sm bg-base-100">
|
||||||
<div className="grid place-items-center py-8">
|
<div className="grid place-items-center py-8">
|
||||||
{loading || !profile ? (
|
{loading || !profile ? (
|
||||||
<div className="avatar opacity-90">
|
<div className="avatar opacity-90">
|
||||||
@ -42,7 +42,7 @@ const AvatarCard: React.FC<AvatarCardProps> = ({
|
|||||||
<div
|
<div
|
||||||
className={`mb-8 rounded-full w-32 h-32 ${
|
className={`mb-8 rounded-full w-32 h-32 ${
|
||||||
avatarRing
|
avatarRing
|
||||||
? 'ring ring-primary ring-offset-base-100 ring-offset-2'
|
? 'ring-3 ring-primary ring-offset-base-100 ring-offset-2'
|
||||||
: ''
|
: ''
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
@ -70,7 +70,7 @@ const AvatarCard: React.FC<AvatarCardProps> = ({
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</h5>
|
</h5>
|
||||||
<div className="mt-3 text-base-content text-opacity-60 font-mono">
|
<div className="mt-3 text-base-content font-mono">
|
||||||
{loading || !profile
|
{loading || !profile
|
||||||
? skeleton({ widthCls: 'w-48', heightCls: 'h-5' })
|
? skeleton({ widthCls: 'w-48', heightCls: 'h-5' })
|
||||||
: profile.bio}
|
: profile.bio}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import LazyImage from '../lazy-image';
|
import LazyImage from '../lazy-image';
|
||||||
import { AiOutlineContainer } from 'react-icons/ai';
|
import { PiNewspaper } from 'react-icons/pi';
|
||||||
import { getDevPost, getMediumPost } from '@arifszn/blog-js';
|
import { getDevPost, getMediumPost } from '@arifszn/blog-js';
|
||||||
import { formatDistance } from 'date-fns';
|
import { formatDistance } from 'date-fns';
|
||||||
import { SanitizedBlog } from '../../interfaces/sanitized-config';
|
import { SanitizedBlog } from '../../interfaces/sanitized-config';
|
||||||
@ -38,7 +38,7 @@ const BlogCard = ({
|
|||||||
const array = [];
|
const array = [];
|
||||||
for (let index = 0; index < blog.limit; index++) {
|
for (let index = 0; index < blog.limit; index++) {
|
||||||
array.push(
|
array.push(
|
||||||
<div className="card shadow-lg compact bg-base-100" key={index}>
|
<div className="card shadow-md card-sm bg-base-100" key={index}>
|
||||||
<div className="p-8 h-full w-full">
|
<div className="p-8 h-full w-full">
|
||||||
<div className="flex items-center flex-col md:flex-row">
|
<div className="flex items-center flex-col md:flex-row">
|
||||||
<div className="avatar mb-5 md:mb-0">
|
<div className="avatar mb-5 md:mb-0">
|
||||||
@ -95,7 +95,7 @@ const BlogCard = ({
|
|||||||
return articles && articles.length ? (
|
return articles && articles.length ? (
|
||||||
articles.slice(0, blog.limit).map((article, index) => (
|
articles.slice(0, blog.limit).map((article, index) => (
|
||||||
<a
|
<a
|
||||||
className="card shadow-lg compact bg-base-100 cursor-pointer"
|
className="card shadow-md card-sm bg-base-100 cursor-pointer"
|
||||||
key={index}
|
key={index}
|
||||||
href={article.link}
|
href={article.link}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@ -140,7 +140,7 @@ const BlogCard = ({
|
|||||||
addSuffix: true,
|
addSuffix: true,
|
||||||
})}
|
})}
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-3 text-base-content text-opacity-60 text-sm">
|
<p className="mt-3 text-base-content text-sm">
|
||||||
{article.description}
|
{article.description}
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-4 flex items-center flex-wrap justify-center md:justify-start">
|
<div className="mt-4 flex items-center flex-wrap justify-center md:justify-start">
|
||||||
@ -162,7 +162,7 @@ const BlogCard = ({
|
|||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center mb-6">
|
<div className="text-center mb-6">
|
||||||
<AiOutlineContainer className="mx-auto h-12 w-12 opacity-30" />
|
<PiNewspaper className="mx-auto h-12 w-12 opacity-30" />
|
||||||
<p className="mt-1 text-sm opacity-50 text-base-content">
|
<p className="mt-1 text-sm opacity-50 text-base-content">
|
||||||
No recent post
|
No recent post
|
||||||
</p>
|
</p>
|
||||||
@ -172,37 +172,41 @@ const BlogCard = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-span-1 lg:col-span-2">
|
<div className="col-span-1 lg:col-span-2">
|
||||||
<div className="grid grid-cols-2 gap-6">
|
<div className="card bg-base-200 shadow-xl border border-base-300">
|
||||||
<div className="col-span-2">
|
<div className="card-body p-8">
|
||||||
<div
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-8">
|
||||||
className={`card compact bg-base-100 ${
|
<div className="flex items-center space-x-3">
|
||||||
loading || (articles && articles.length)
|
|
||||||
? 'shadow bg-opacity-40'
|
|
||||||
: 'shadow-lg'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div className="card-body">
|
|
||||||
<div className="mx-3 mb-2">
|
|
||||||
<h5 className="card-title">
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
skeleton({ widthCls: 'w-28', heightCls: 'h-8' })
|
skeleton({
|
||||||
|
widthCls: 'w-12',
|
||||||
|
heightCls: 'h-12',
|
||||||
|
className: 'rounded-xl',
|
||||||
|
})
|
||||||
) : (
|
) : (
|
||||||
<span className="text-base-content opacity-70">
|
<div className="flex items-center justify-center w-12 h-12 bg-primary/10 rounded-xl">
|
||||||
My Articles
|
<PiNewspaper className="text-2xl" />
|
||||||
</span>
|
</div>
|
||||||
)}
|
)}
|
||||||
</h5>
|
<div className="min-w-0 flex-1">
|
||||||
|
<h3 className="text-base sm:text-lg font-bold text-base-content truncate">
|
||||||
|
{loading
|
||||||
|
? skeleton({ widthCls: 'w-28', heightCls: 'h-8' })
|
||||||
|
: 'My Articles'}
|
||||||
|
</h3>
|
||||||
|
<div className="text-base-content/60 text-xs sm:text-sm mt-1 truncate">
|
||||||
|
{loading
|
||||||
|
? skeleton({ widthCls: 'w-32', heightCls: 'h-4' })
|
||||||
|
: 'Recent posts'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-2">
|
|
||||||
<div className="grid grid-cols-1 gap-6">
|
<div className="grid grid-cols-1 gap-6">
|
||||||
{loading || !articles ? renderSkeleton() : renderArticles()}
|
{loading || !articles ? renderSkeleton() : renderArticles()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -59,7 +59,7 @@ const CertificationCard = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card shadow-lg compact bg-base-100">
|
<div className="card shadow-lg card-sm bg-base-100">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="mx-3">
|
<div className="mx-3">
|
||||||
<h5 className="card-title">
|
<h5 className="card-title">
|
||||||
@ -72,7 +72,7 @@ const CertificationCard = ({
|
|||||||
)}
|
)}
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-base-content text-opacity-60">
|
<div className="text-base-content">
|
||||||
<ol className="relative border-l border-base-300 border-opacity-30 my-2 mx-4">
|
<ol className="relative border-l border-base-300 border-opacity-30 my-2 mx-4">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
renderSkeleton()
|
renderSkeleton()
|
||||||
|
|||||||
@ -66,12 +66,12 @@ const ListItem: React.FC<{
|
|||||||
}> = ({ icon, title, value, link, skeleton = false }) => {
|
}> = ({ icon, title, value, link, skeleton = false }) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-start py-2 px-1 items-center">
|
<div className="flex justify-start py-2 px-1 items-center">
|
||||||
<div className="flex-grow font-medium gap-2 flex items-center my-1">
|
<div className="grow font-medium gap-2 flex items-center my-1">
|
||||||
{icon} {title}
|
{icon} {title}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
skeleton ? 'flex-grow' : ''
|
skeleton ? 'grow' : ''
|
||||||
} text-sm font-normal text-right mr-2 ml-3 ${link ? 'truncate' : ''}`}
|
} text-sm font-normal text-right mr-2 ml-3 ${link ? 'truncate' : ''}`}
|
||||||
style={{
|
style={{
|
||||||
wordBreak: 'break-word',
|
wordBreak: 'break-word',
|
||||||
@ -124,12 +124,12 @@ const OrganizationItem: React.FC<{
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-start py-2 px-1 items-center">
|
<div className="flex justify-start py-2 px-1 items-center">
|
||||||
<div className="flex-grow font-medium gap-2 flex items-center my-1">
|
<div className="grow font-medium gap-2 flex items-center my-1">
|
||||||
{icon} {title}
|
{icon} {title}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
skeleton ? 'flex-grow' : ''
|
skeleton ? 'grow' : ''
|
||||||
} text-sm font-normal text-right mr-2 ml-3 space-x-2 ${link ? 'truncate' : ''}`}
|
} text-sm font-normal text-right mr-2 ml-3 space-x-2 ${link ? 'truncate' : ''}`}
|
||||||
style={{
|
style={{
|
||||||
wordBreak: 'break-word',
|
wordBreak: 'break-word',
|
||||||
@ -169,9 +169,9 @@ const DetailsCard = ({ profile, loading, social, github }: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card shadow-lg compact bg-base-100">
|
<div className="card shadow-lg card-sm bg-base-100">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="text-base-content text-opacity-60">
|
<div className="text-base-content">
|
||||||
{loading || !profile ? (
|
{loading || !profile ? (
|
||||||
renderSkeleton()
|
renderSkeleton()
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@ -53,7 +53,7 @@ const EducationCard = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card shadow-lg compact bg-base-100">
|
<div className="card shadow-lg card-sm bg-base-100">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="mx-3">
|
<div className="mx-3">
|
||||||
<h5 className="card-title">
|
<h5 className="card-title">
|
||||||
@ -64,7 +64,7 @@ const EducationCard = ({
|
|||||||
)}
|
)}
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-base-content text-opacity-60">
|
<div className="text-base-content">
|
||||||
<ol className="relative border-l border-base-300 border-opacity-30 my-2 mx-4">
|
<ol className="relative border-l border-base-300 border-opacity-30 my-2 mx-4">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
renderSkeleton()
|
renderSkeleton()
|
||||||
|
|||||||
@ -16,9 +16,7 @@ const ErrorPage: React.FC<CustomError> = (props) => {
|
|||||||
{`${props.status}`}
|
{`${props.status}`}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg pb-2 text-base-content">{props.title}</p>
|
<p className="text-lg pb-2 text-base-content">{props.title}</p>
|
||||||
<div className="text-base-content text-opacity-60">
|
<div className="text-base-content">{props.subTitle}</div>
|
||||||
{props.subTitle}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -58,7 +58,7 @@ const ExperienceCard = ({
|
|||||||
return array;
|
return array;
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="card shadow-lg compact bg-base-100">
|
<div className="card shadow-lg card-sm bg-base-100">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="mx-3">
|
<div className="mx-3">
|
||||||
<h5 className="card-title">
|
<h5 className="card-title">
|
||||||
@ -69,7 +69,7 @@ const ExperienceCard = ({
|
|||||||
)}
|
)}
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-base-content text-opacity-60">
|
<div className="text-base-content">
|
||||||
<ol className="relative border-l border-base-300 border-opacity-30 my-2 mx-4">
|
<ol className="relative border-l border-base-300 border-opacity-30 my-2 mx-4">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
renderSkeleton()
|
renderSkeleton()
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Fragment } from 'react';
|
import { Fragment } from 'react';
|
||||||
import LazyImage from '../lazy-image';
|
import LazyImage from '../lazy-image';
|
||||||
|
import { MdOpenInNew } from 'react-icons/md';
|
||||||
import { ga, skeleton } from '../../utils';
|
import { ga, skeleton } from '../../utils';
|
||||||
import { SanitizedExternalProject } from '../../interfaces/sanitized-config';
|
import { SanitizedExternalProject } from '../../interfaces/sanitized-config';
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ const ExternalProjectCard = ({
|
|||||||
const array = [];
|
const array = [];
|
||||||
for (let index = 0; index < externalProjects.length; index++) {
|
for (let index = 0; index < externalProjects.length; index++) {
|
||||||
array.push(
|
array.push(
|
||||||
<div className="card shadow-lg compact bg-base-100" key={index}>
|
<div className="card shadow-md card-sm bg-base-100" key={index}>
|
||||||
<div className="p-8 h-full w-full">
|
<div className="p-8 h-full w-full">
|
||||||
<div className="flex items-center flex-col">
|
<div className="flex items-center flex-col">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
@ -69,7 +70,7 @@ const ExternalProjectCard = ({
|
|||||||
const renderExternalProjects = () => {
|
const renderExternalProjects = () => {
|
||||||
return externalProjects.map((item, index) => (
|
return externalProjects.map((item, index) => (
|
||||||
<a
|
<a
|
||||||
className="card shadow-lg compact bg-base-100 cursor-pointer"
|
className="card shadow-md card-sm bg-base-100 cursor-pointer"
|
||||||
key={index}
|
key={index}
|
||||||
href={item.link}
|
href={item.link}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@ -111,7 +112,7 @@ const ExternalProjectCard = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<p className="mt-2 text-base-content text-opacity-60 text-sm text-justify">
|
<p className="mt-2 text-base-content text-sm text-justify">
|
||||||
{item.description}
|
{item.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -126,31 +127,41 @@ const ExternalProjectCard = ({
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="col-span-1 lg:col-span-2">
|
<div className="col-span-1 lg:col-span-2">
|
||||||
<div className="grid grid-cols-2 gap-6">
|
<div className="card bg-base-200 shadow-xl border border-base-300">
|
||||||
<div className="col-span-2">
|
<div className="card-body p-8">
|
||||||
<div className="card compact bg-base-100 shadow bg-opacity-40">
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-8">
|
||||||
<div className="card-body">
|
<div className="flex items-center space-x-3">
|
||||||
<div className="mx-3 flex items-center justify-between mb-2">
|
|
||||||
<h5 className="card-title">
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
skeleton({ widthCls: 'w-40', heightCls: 'h-8' })
|
skeleton({
|
||||||
|
widthCls: 'w-12',
|
||||||
|
heightCls: 'h-12',
|
||||||
|
className: 'rounded-xl',
|
||||||
|
})
|
||||||
) : (
|
) : (
|
||||||
<span className="text-base-content opacity-70">
|
<div className="flex items-center justify-center w-12 h-12 bg-primary/10 rounded-xl">
|
||||||
{header}
|
<MdOpenInNew className="text-2xl" />
|
||||||
</span>
|
</div>
|
||||||
)}
|
)}
|
||||||
</h5>
|
<div className="min-w-0 flex-1">
|
||||||
|
<h3 className="text-base sm:text-lg font-bold text-base-content truncate">
|
||||||
|
{loading
|
||||||
|
? skeleton({ widthCls: 'w-40', heightCls: 'h-8' })
|
||||||
|
: header}
|
||||||
|
</h3>
|
||||||
|
<div className="text-base-content/60 text-xs sm:text-sm mt-1 truncate">
|
||||||
|
{loading
|
||||||
|
? skeleton({ widthCls: 'w-32', heightCls: 'h-4' })
|
||||||
|
: `Showcasing ${externalProjects.length} external projects`}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-2">
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
{loading ? renderSkeleton() : renderExternalProjects()}
|
{loading ? renderSkeleton() : renderExternalProjects()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Fragment } from 'react';
|
import { Fragment } from 'react';
|
||||||
import { AiOutlineFork, AiOutlineStar } from 'react-icons/ai';
|
import { AiOutlineFork, AiOutlineStar, AiOutlineGithub } from 'react-icons/ai';
|
||||||
import { MdInsertLink } from 'react-icons/md';
|
import { MdInsertLink } from 'react-icons/md';
|
||||||
import { ga, getLanguageColor, skeleton } from '../../utils';
|
import { ga, getLanguageColor, skeleton } from '../../utils';
|
||||||
import { GithubProject } from '../../interfaces/github-project';
|
import { GithubProject } from '../../interfaces/github-project';
|
||||||
@ -9,14 +9,12 @@ const GithubProjectCard = ({
|
|||||||
githubProjects,
|
githubProjects,
|
||||||
loading,
|
loading,
|
||||||
limit,
|
limit,
|
||||||
username,
|
|
||||||
googleAnalyticsId,
|
googleAnalyticsId,
|
||||||
}: {
|
}: {
|
||||||
header: string;
|
header: string;
|
||||||
githubProjects: GithubProject[];
|
githubProjects: GithubProject[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
limit: number;
|
limit: number;
|
||||||
username: string;
|
|
||||||
googleAnalyticsId?: string;
|
googleAnalyticsId?: string;
|
||||||
}) => {
|
}) => {
|
||||||
if (!loading && githubProjects.length === 0) {
|
if (!loading && githubProjects.length === 0) {
|
||||||
@ -27,7 +25,7 @@ const GithubProjectCard = ({
|
|||||||
const array = [];
|
const array = [];
|
||||||
for (let index = 0; index < limit; index++) {
|
for (let index = 0; index < limit; index++) {
|
||||||
array.push(
|
array.push(
|
||||||
<div className="card shadow-lg compact bg-base-100" key={index}>
|
<div className="card shadow-md card-sm bg-base-100" key={index}>
|
||||||
<div className="flex justify-between flex-col p-8 h-full w-full">
|
<div className="flex justify-between flex-col p-8 h-full w-full">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
@ -51,7 +49,7 @@ const GithubProjectCard = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<div className="flex flex-grow">
|
<div className="flex grow">
|
||||||
<span className="mr-3 flex items-center">
|
<span className="mr-3 flex items-center">
|
||||||
{skeleton({ widthCls: 'w-12', heightCls: 'h-4' })}
|
{skeleton({ widthCls: 'w-12', heightCls: 'h-4' })}
|
||||||
</span>
|
</span>
|
||||||
@ -76,7 +74,7 @@ const GithubProjectCard = ({
|
|||||||
const renderProjects = () => {
|
const renderProjects = () => {
|
||||||
return githubProjects.map((item, index) => (
|
return githubProjects.map((item, index) => (
|
||||||
<a
|
<a
|
||||||
className="card shadow-lg compact bg-base-100 cursor-pointer"
|
className="card shadow-md card-sm bg-base-100 cursor-pointer"
|
||||||
href={item.html_url}
|
href={item.html_url}
|
||||||
key={index}
|
key={index}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@ -84,9 +82,7 @@ const GithubProjectCard = ({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (googleAnalyticsId) {
|
if (googleAnalyticsId) {
|
||||||
ga.event('Click project', {
|
ga.event('Click project', { project: item.name });
|
||||||
project: item.name,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -103,12 +99,12 @@ const GithubProjectCard = ({
|
|||||||
<span>{item.name}</span>
|
<span>{item.name}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="mb-5 mt-1 text-base-content text-opacity-60 text-sm">
|
<p className="mb-5 mt-1 text-base-content text-sm">
|
||||||
{item.description}
|
{item.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between text-sm text-base-content text-opacity-60 truncate">
|
<div className="flex justify-between text-sm text-base-content truncate">
|
||||||
<div className="flex flex-grow">
|
<div className="flex grow">
|
||||||
<span className="mr-3 flex items-center">
|
<span className="mr-3 flex items-center">
|
||||||
<AiOutlineStar className="mr-0.5" />
|
<AiOutlineStar className="mr-0.5" />
|
||||||
<span>{item.stargazers_count}</span>
|
<span>{item.stargazers_count}</span>
|
||||||
@ -136,43 +132,44 @@ const GithubProjectCard = ({
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="col-span-1 lg:col-span-2">
|
<div className="col-span-1 lg:col-span-2">
|
||||||
<div className="grid grid-cols-2 gap-6">
|
<div className="card bg-base-200 shadow-xl border border-base-300">
|
||||||
<div className="col-span-2">
|
<div className="card-body p-8">
|
||||||
<div className="card compact bg-base-100 shadow bg-opacity-40">
|
{/* Enhanced Header Section */}
|
||||||
<div className="card-body">
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-8">
|
||||||
<div className="mx-3 flex items-center justify-between mb-2">
|
<div className="flex items-center space-x-3">
|
||||||
<h5 className="card-title">
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
skeleton({ widthCls: 'w-40', heightCls: 'h-8' })
|
skeleton({
|
||||||
|
widthCls: 'w-12',
|
||||||
|
heightCls: 'h-12',
|
||||||
|
className: 'rounded-xl',
|
||||||
|
})
|
||||||
) : (
|
) : (
|
||||||
<span className="text-base-content opacity-70">
|
<div className="flex items-center justify-center w-12 h-12 bg-primary/10 rounded-xl">
|
||||||
{header}
|
<AiOutlineGithub className="text-2xl" />
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</h5>
|
|
||||||
{loading ? (
|
|
||||||
skeleton({ widthCls: 'w-10', heightCls: 'h-5' })
|
|
||||||
) : (
|
|
||||||
<a
|
|
||||||
href={`https://github.com/${username}?tab=repositories`}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="text-base-content opacity-50 hover:underline"
|
|
||||||
>
|
|
||||||
See All
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-2">
|
)}
|
||||||
|
<div className="min-w-0 flex-1">
|
||||||
|
<h3 className="text-base sm:text-lg font-bold text-base-content truncate">
|
||||||
|
{loading
|
||||||
|
? skeleton({ widthCls: 'w-48', heightCls: 'h-8' })
|
||||||
|
: header}
|
||||||
|
</h3>
|
||||||
|
<div className="text-base-content/60 text-xs sm:text-sm mt-1 truncate">
|
||||||
|
{loading
|
||||||
|
? skeleton({ widthCls: 'w-32', heightCls: 'h-4' })
|
||||||
|
: `Showcasing ${githubProjects.length} featured repositories`}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Projects Grid */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
{loading ? renderSkeleton() : renderProjects()}
|
{loading ? renderSkeleton() : renderProjects()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,12 +8,10 @@ import {
|
|||||||
INVALID_GITHUB_USERNAME_ERROR,
|
INVALID_GITHUB_USERNAME_ERROR,
|
||||||
setTooManyRequestError,
|
setTooManyRequestError,
|
||||||
} from '../constants/errors';
|
} from '../constants/errors';
|
||||||
import { HelmetProvider } from 'react-helmet-async';
|
|
||||||
import '../assets/index.css';
|
import '../assets/index.css';
|
||||||
import { getInitialTheme, getSanitizedConfig, setupHotjar } from '../utils';
|
import { getInitialTheme, getSanitizedConfig, setupHotjar } from '../utils';
|
||||||
import { SanitizedConfig } from '../interfaces/sanitized-config';
|
import { SanitizedConfig } from '../interfaces/sanitized-config';
|
||||||
import ErrorPage from './error-page';
|
import ErrorPage from './error-page';
|
||||||
import HeadTagEditor from './head-tag-editor';
|
|
||||||
import { DEFAULT_THEMES } from '../constants/default-themes';
|
import { DEFAULT_THEMES } from '../constants/default-themes';
|
||||||
import ThemeChanger from './theme-changer';
|
import ThemeChanger from './theme-changer';
|
||||||
import { BG_COLOR } from '../constants';
|
import { BG_COLOR } from '../constants';
|
||||||
@ -180,7 +178,6 @@ const GitProfile = ({ config }: { config: Config }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HelmetProvider>
|
|
||||||
<div className="fade-in h-screen">
|
<div className="fade-in h-screen">
|
||||||
{error ? (
|
{error ? (
|
||||||
<ErrorPage
|
<ErrorPage
|
||||||
@ -190,10 +187,6 @@ const GitProfile = ({ config }: { config: Config }) => {
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<HeadTagEditor
|
|
||||||
googleAnalyticsId={sanitizedConfig.googleAnalytics.id}
|
|
||||||
appliedTheme={theme}
|
|
||||||
/>
|
|
||||||
<div className={`p-4 lg:p-10 min-h-full ${BG_COLOR}`}>
|
<div className={`p-4 lg:p-10 min-h-full ${BG_COLOR}`}>
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 rounded-box">
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 rounded-box">
|
||||||
<div className="col-span-1">
|
<div className="col-span-1">
|
||||||
@ -252,7 +245,6 @@ const GitProfile = ({ config }: { config: Config }) => {
|
|||||||
limit={sanitizedConfig.projects.github.automatic.limit}
|
limit={sanitizedConfig.projects.github.automatic.limit}
|
||||||
githubProjects={githubProjects}
|
githubProjects={githubProjects}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
username={sanitizedConfig.github.username}
|
|
||||||
googleAnalyticsId={sanitizedConfig.googleAnalytics.id}
|
googleAnalyticsId={sanitizedConfig.googleAnalytics.id}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -262,8 +254,7 @@ const GitProfile = ({ config }: { config: Config }) => {
|
|||||||
publications={sanitizedConfig.publications}
|
publications={sanitizedConfig.publications}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{sanitizedConfig.projects.external.projects.length !==
|
{sanitizedConfig.projects.external.projects.length !== 0 && (
|
||||||
0 && (
|
|
||||||
<ExternalProjectCard
|
<ExternalProjectCard
|
||||||
loading={loading}
|
loading={loading}
|
||||||
header={sanitizedConfig.projects.external.header}
|
header={sanitizedConfig.projects.external.header}
|
||||||
@ -288,7 +279,7 @@ const GitProfile = ({ config }: { config: Config }) => {
|
|||||||
<footer
|
<footer
|
||||||
className={`p-4 footer ${BG_COLOR} text-base-content footer-center`}
|
className={`p-4 footer ${BG_COLOR} text-base-content footer-center`}
|
||||||
>
|
>
|
||||||
<div className="card compact bg-base-100 shadow">
|
<div className="card card-sm bg-base-100 shadow-sm">
|
||||||
<Footer content={sanitizedConfig.footer} loading={loading} />
|
<Footer content={sanitizedConfig.footer} loading={loading} />
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
@ -296,7 +287,6 @@ const GitProfile = ({ config }: { config: Config }) => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</HelmetProvider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,47 +0,0 @@
|
|||||||
import { Helmet } from 'react-helmet-async';
|
|
||||||
import { isDarkishTheme } from '../../utils';
|
|
||||||
|
|
||||||
type HeadTagEditorProps = {
|
|
||||||
googleAnalyticsId?: string;
|
|
||||||
appliedTheme: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the head tag editor component.
|
|
||||||
*
|
|
||||||
* @param {HeadTagEditorProps} googleAnalyticsId - The Google Analytics ID.
|
|
||||||
* @param {HeadTagEditorProps} appliedTheme - The applied theme.
|
|
||||||
* @return {React.ReactElement} The head tag editor component.
|
|
||||||
*/
|
|
||||||
const HeadTagEditor: React.FC<HeadTagEditorProps> = ({
|
|
||||||
googleAnalyticsId,
|
|
||||||
appliedTheme,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<Helmet>
|
|
||||||
<meta
|
|
||||||
name="theme-color"
|
|
||||||
content={isDarkishTheme(appliedTheme) ? '#000000' : '#ffffff'}
|
|
||||||
/>
|
|
||||||
{googleAnalyticsId && (
|
|
||||||
<>
|
|
||||||
<script
|
|
||||||
async
|
|
||||||
src={`https://www.googletagmanager.com/gtag/js?id=${googleAnalyticsId}`}
|
|
||||||
></script>
|
|
||||||
<script>
|
|
||||||
{`window.dataLayer = window.dataLayer || [];
|
|
||||||
function gtag() {
|
|
||||||
dataLayer.push(arguments);
|
|
||||||
}
|
|
||||||
gtag('js', new Date());
|
|
||||||
gtag('config', '${googleAnalyticsId}');
|
|
||||||
`}
|
|
||||||
</script>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Helmet>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default HeadTagEditor;
|
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { Fragment } from 'react';
|
import { Fragment } from 'react';
|
||||||
|
import { AiOutlineBook } from 'react-icons/ai';
|
||||||
import { SanitizedPublication } from '../../interfaces/sanitized-config';
|
import { SanitizedPublication } from '../../interfaces/sanitized-config';
|
||||||
import { skeleton } from '../../utils';
|
import { skeleton } from '../../utils';
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ const PublicationCard = ({
|
|||||||
const array = [];
|
const array = [];
|
||||||
for (let index = 0; index < publications.length; index++) {
|
for (let index = 0; index < publications.length; index++) {
|
||||||
array.push(
|
array.push(
|
||||||
<div className="card shadow-lg compact bg-base-100" key={index}>
|
<div className="card shadow-md card-sm bg-base-100" key={index}>
|
||||||
<div className="p-8 h-full w-full">
|
<div className="p-8 h-full w-full">
|
||||||
<div className="flex items-center flex-col">
|
<div className="flex items-center flex-col">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
@ -76,7 +77,7 @@ const PublicationCard = ({
|
|||||||
const renderPublications = () => {
|
const renderPublications = () => {
|
||||||
return publications.map((item, index) => (
|
return publications.map((item, index) => (
|
||||||
<a
|
<a
|
||||||
className="card shadow-lg compact bg-base-100 cursor-pointer"
|
className="card shadow-md card-sm bg-base-100 cursor-pointer"
|
||||||
key={index}
|
key={index}
|
||||||
href={item.link}
|
href={item.link}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@ -104,7 +105,7 @@ const PublicationCard = ({
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{item.description && (
|
{item.description && (
|
||||||
<p className="mt-2 text-base-content text-opacity-60 text-sm text-justify">
|
<p className="mt-2 text-base-content text-sm text-justify">
|
||||||
{item.description}
|
{item.description}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
@ -120,31 +121,41 @@ const PublicationCard = ({
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="col-span-1 lg:col-span-2">
|
<div className="col-span-1 lg:col-span-2">
|
||||||
<div className="grid grid-cols-2 gap-6">
|
<div className="card bg-base-200 shadow-xl border border-base-300">
|
||||||
<div className="col-span-2">
|
<div className="card-body p-8">
|
||||||
<div className="card compact bg-base-100 shadow bg-opacity-40">
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-8">
|
||||||
<div className="card-body">
|
<div className="flex items-center space-x-3">
|
||||||
<div className="mx-3 flex items-center justify-between mb-2">
|
|
||||||
<h5 className="card-title">
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
skeleton({ widthCls: 'w-40', heightCls: 'h-8' })
|
skeleton({
|
||||||
|
widthCls: 'w-12',
|
||||||
|
heightCls: 'h-12',
|
||||||
|
className: 'rounded-xl',
|
||||||
|
})
|
||||||
) : (
|
) : (
|
||||||
<span className="text-base-content opacity-70">
|
<div className="flex items-center justify-center w-12 h-12 bg-primary/10 rounded-xl">
|
||||||
Publications
|
<AiOutlineBook className="text-2xl" />
|
||||||
</span>
|
</div>
|
||||||
)}
|
)}
|
||||||
</h5>
|
<div className="min-w-0 flex-1">
|
||||||
|
<h3 className="text-base sm:text-lg font-bold text-base-content truncate">
|
||||||
|
{loading
|
||||||
|
? skeleton({ widthCls: 'w-40', heightCls: 'h-8' })
|
||||||
|
: 'Publications'}
|
||||||
|
</h3>
|
||||||
|
<div className="text-base-content/60 text-xs sm:text-sm mt-1 truncate">
|
||||||
|
{loading
|
||||||
|
? skeleton({ widthCls: 'w-32', heightCls: 'h-4' })
|
||||||
|
: `Showcasing ${publications.length} publications`}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-2">
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
{loading ? renderSkeleton() : renderPublications()}
|
{loading ? renderSkeleton() : renderPublications()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -21,7 +21,7 @@ const SkillCard = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card shadow-lg compact bg-base-100">
|
<div className="card shadow-lg card-sm bg-base-100">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="mx-3">
|
<div className="mx-3">
|
||||||
<h5 className="card-title">
|
<h5 className="card-title">
|
||||||
@ -33,14 +33,11 @@ const SkillCard = ({
|
|||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-3 flow-root">
|
<div className="p-3 flow-root">
|
||||||
<div className="-m-1 flex flex-wrap justify-center">
|
<div className="-m-1 flex flex-wrap justify-center gap-2">
|
||||||
{loading
|
{loading
|
||||||
? renderSkeleton()
|
? renderSkeleton()
|
||||||
: skills.map((skill, index) => (
|
: skills.map((skill, index) => (
|
||||||
<div
|
<div key={index} className="badge badge-primary badge-sm">
|
||||||
key={index}
|
|
||||||
className="m-1 text-xs inline-flex items-center font-bold leading-sm px-3 py-1 badge-primary bg-opacity-90 rounded-full"
|
|
||||||
>
|
|
||||||
{skill}
|
{skill}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { AiOutlineControl } from 'react-icons/ai';
|
import { RiDice4Line } from 'react-icons/ri';
|
||||||
import { SanitizedThemeConfig } from '../../interfaces/sanitized-config';
|
import { SanitizedThemeConfig } from '../../interfaces/sanitized-config';
|
||||||
import { LOCAL_STORAGE_KEY_NAME } from '../../constants';
|
import { LOCAL_STORAGE_KEY_NAME } from '../../constants';
|
||||||
import { skeleton } from '../../utils';
|
import { skeleton } from '../../utils';
|
||||||
@ -40,7 +40,7 @@ const ThemeChanger = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card overflow-visible shadow-lg compact bg-base-100">
|
<div className="card overflow-visible shadow-lg card-sm bg-base-100">
|
||||||
<div className="flex-row items-center space-x-4 flex pl-6 pr-2 py-4">
|
<div className="flex-row items-center space-x-4 flex pl-6 pr-2 py-4">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h5 className="card-title">
|
<h5 className="card-title">
|
||||||
@ -54,7 +54,7 @@ const ThemeChanger = ({
|
|||||||
<span className="text-base-content opacity-70">Theme</span>
|
<span className="text-base-content opacity-70">Theme</span>
|
||||||
)}
|
)}
|
||||||
</h5>
|
</h5>
|
||||||
<span className="text-base-content text-opacity-40 capitalize text-sm">
|
<span className="text-base-content/50 capitalize text-sm">
|
||||||
{loading
|
{loading
|
||||||
? skeleton({ widthCls: 'w-16', heightCls: 'h-5' })
|
? skeleton({ widthCls: 'w-16', heightCls: 'h-5' })
|
||||||
: theme === themeConfig.defaultTheme
|
: theme === themeConfig.defaultTheme
|
||||||
@ -65,7 +65,7 @@ const ThemeChanger = ({
|
|||||||
<div className="flex-0">
|
<div className="flex-0">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
skeleton({
|
skeleton({
|
||||||
widthCls: 'w-14 md:w-28',
|
widthCls: 'w-12',
|
||||||
heightCls: 'h-10',
|
heightCls: 'h-10',
|
||||||
className: 'mr-6',
|
className: 'mr-6',
|
||||||
})
|
})
|
||||||
@ -73,23 +73,15 @@ const ThemeChanger = ({
|
|||||||
<div title="Change Theme" className="dropdown dropdown-end">
|
<div title="Change Theme" className="dropdown dropdown-end">
|
||||||
<div
|
<div
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
className="btn btn-ghost m-1 normal-case opacity-50 text-base-content"
|
className="btn btn-ghost m-1 normal-case opacity-50 text-base-content flex items-center whitespace-nowrap"
|
||||||
>
|
>
|
||||||
<AiOutlineControl className="inline-block w-5 h-5 stroke-current md:mr-2" />
|
<RiDice4Line className="inline-block w-5 h-5 stroke-current" />
|
||||||
<span className="hidden md:inline">Change Theme</span>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 1792 1792"
|
|
||||||
className="inline-block w-4 h-4 ml-1 fill-current"
|
|
||||||
>
|
|
||||||
<path d="M1395 736q0 13-10 23l-466 466q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l50-50q10-10 23-10t23 10l393 393 393-393q10-10 23-10t23 10l50 50q10 10 10 23z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
className="mt-16 overflow-y-auto shadow-2xl top-px dropdown-content max-h-96 w-52 rounded-lg bg-base-200 text-base-content z-10"
|
className="mt-16 overflow-y-auto shadow-2xl top-px dropdown-content max-h-96 min-w-max rounded-lg bg-base-200 text-base-content z-10"
|
||||||
>
|
>
|
||||||
<ul className="p-4 menu compact">
|
<ul className="p-4 menu menu-sm">
|
||||||
{[
|
{[
|
||||||
themeConfig.defaultTheme,
|
themeConfig.defaultTheme,
|
||||||
...themeConfig.themes.filter(
|
...themeConfig.themes.filter(
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
export const DEFAULT_CUSTOM_THEME = {
|
|
||||||
primary: '#fc055b',
|
|
||||||
secondary: '#219aaf',
|
|
||||||
accent: '#e8d03a',
|
|
||||||
neutral: '#2A2730',
|
|
||||||
'base-100': '#E3E3ED',
|
|
||||||
'--rounded-box': '3rem',
|
|
||||||
'--rounded-btn': '3rem',
|
|
||||||
};
|
|
||||||
@ -31,5 +31,8 @@ export const DEFAULT_THEMES = [
|
|||||||
'dim',
|
'dim',
|
||||||
'nord',
|
'nord',
|
||||||
'sunset',
|
'sunset',
|
||||||
|
'caramellatte',
|
||||||
|
'abyss',
|
||||||
|
'silk',
|
||||||
'procyon',
|
'procyon',
|
||||||
];
|
];
|
||||||
|
|||||||
@ -116,23 +116,12 @@ export interface SanitizedBlog {
|
|||||||
limit: number;
|
limit: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SanitizedCustomTheme {
|
|
||||||
primary: string;
|
|
||||||
secondary: string;
|
|
||||||
accent: string;
|
|
||||||
neutral: string;
|
|
||||||
'base-100': string;
|
|
||||||
'--rounded-box': string;
|
|
||||||
'--rounded-btn': string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SanitizedThemeConfig {
|
export interface SanitizedThemeConfig {
|
||||||
defaultTheme: string;
|
defaultTheme: string;
|
||||||
disableSwitch: boolean;
|
disableSwitch: boolean;
|
||||||
respectPrefersColorScheme: boolean;
|
respectPrefersColorScheme: boolean;
|
||||||
displayAvatarRing: boolean;
|
displayAvatarRing: boolean;
|
||||||
themes: Array<string>;
|
themes: Array<string>;
|
||||||
customTheme: SanitizedCustomTheme;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SanitizedConfig {
|
export interface SanitizedConfig {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
|
import React from 'react';
|
||||||
import { hotjar } from 'react-hotjar';
|
import { hotjar } from 'react-hotjar';
|
||||||
import { LOCAL_STORAGE_KEY_NAME } from '../constants';
|
import { LOCAL_STORAGE_KEY_NAME } from '../constants';
|
||||||
import { DEFAULT_CUSTOM_THEME } from '../constants/default-custom-theme';
|
|
||||||
import { DEFAULT_THEMES } from '../constants/default-themes';
|
import { DEFAULT_THEMES } from '../constants/default-themes';
|
||||||
import colors from '../data/colors.json';
|
import colors from '../data/colors.json';
|
||||||
import {
|
import {
|
||||||
@ -124,29 +125,6 @@ export const getSanitizedConfig = (
|
|||||||
config?.themeConfig?.respectPrefersColorScheme || false,
|
config?.themeConfig?.respectPrefersColorScheme || false,
|
||||||
displayAvatarRing: config?.themeConfig?.displayAvatarRing ?? true,
|
displayAvatarRing: config?.themeConfig?.displayAvatarRing ?? true,
|
||||||
themes: config?.themeConfig?.themes || DEFAULT_THEMES,
|
themes: config?.themeConfig?.themes || DEFAULT_THEMES,
|
||||||
customTheme: {
|
|
||||||
primary:
|
|
||||||
config?.themeConfig?.customTheme?.primary ||
|
|
||||||
DEFAULT_CUSTOM_THEME.primary,
|
|
||||||
secondary:
|
|
||||||
config?.themeConfig?.customTheme?.secondary ||
|
|
||||||
DEFAULT_CUSTOM_THEME.secondary,
|
|
||||||
accent:
|
|
||||||
config?.themeConfig?.customTheme?.accent ||
|
|
||||||
DEFAULT_CUSTOM_THEME.accent,
|
|
||||||
neutral:
|
|
||||||
config?.themeConfig?.customTheme?.neutral ||
|
|
||||||
DEFAULT_CUSTOM_THEME.neutral,
|
|
||||||
'base-100':
|
|
||||||
config?.themeConfig?.customTheme?.['base-100'] ||
|
|
||||||
DEFAULT_CUSTOM_THEME['base-100'],
|
|
||||||
'--rounded-box':
|
|
||||||
config?.themeConfig?.customTheme?.['--rounded-box'] ||
|
|
||||||
DEFAULT_CUSTOM_THEME['--rounded-box'],
|
|
||||||
'--rounded-btn':
|
|
||||||
config?.themeConfig?.customTheme?.['--rounded-btn'] ||
|
|
||||||
DEFAULT_CUSTOM_THEME['--rounded-btn'],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
footer: config?.footer,
|
footer: config?.footer,
|
||||||
enablePWA: config?.enablePWA ?? true,
|
enablePWA: config?.enablePWA ?? true,
|
||||||
@ -194,7 +172,7 @@ export const skeleton = ({
|
|||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
shape?: string;
|
shape?: string;
|
||||||
className?: string | null;
|
className?: string | null;
|
||||||
}): JSX.Element => {
|
}): React.JSX.Element => {
|
||||||
const classNames = ['bg-base-300', 'animate-pulse', shape];
|
const classNames = ['bg-base-300', 'animate-pulse', shape];
|
||||||
if (className) {
|
if (className) {
|
||||||
classNames.push(className);
|
classNames.push(className);
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
import CONFIG from './gitprofile.config';
|
|
||||||
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
export default {
|
|
||||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
|
||||||
theme: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
plugins: [require('daisyui')],
|
|
||||||
daisyui: {
|
|
||||||
logs: false,
|
|
||||||
themes: [
|
|
||||||
...CONFIG.themeConfig.themes,
|
|
||||||
{ procyon: CONFIG.themeConfig.customTheme },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -15,6 +15,16 @@ export default defineConfig({
|
|||||||
metaTitle: CONFIG.seo.title,
|
metaTitle: CONFIG.seo.title,
|
||||||
metaDescription: CONFIG.seo.description,
|
metaDescription: CONFIG.seo.description,
|
||||||
metaImageURL: CONFIG.seo.imageURL,
|
metaImageURL: CONFIG.seo.imageURL,
|
||||||
|
googleAnalyticsScript: CONFIG.googleAnalytics.id
|
||||||
|
? `<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=${CONFIG.googleAnalytics.id}"></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){dataLayer.push(arguments);}
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', '${CONFIG.googleAnalytics.id}');
|
||||||
|
</script>`
|
||||||
|
: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user