Compare commits

..

No commits in common. "main" and "team" have entirely different histories.
main ... team

6 changed files with 4 additions and 455 deletions

View File

@ -1,104 +0,0 @@
import { Metadata } from 'next';
import Link from 'next/link';
import React from 'react';
export const metadata: Metadata = {
title: 'Blog',
};
const blogs = [
{
id: 1,
image: '/assets/images/blog/image-1.jpg',
title: 'Excessive sugar is harmful',
description: 'Sugar consumption can have serious effects on your health if taken in excess. Learn how to reduce it.',
author: 'Alma Clark',
profile: '/assets/images/profile-1.jpeg',
date: '06 May',
slug: '/blog/1',
},
{
id: 2,
image: '/assets/images/blog/image-1.jpg',
title: 'Creative Photography',
description: 'Photography is not just about capturing pictures, but emotions and stories through your lens.',
author: 'Alma Clark',
profile: '/assets/images/profile-2.jpeg',
date: '06 May',
slug: '/blog/2',
},
{
id: 3,
image: '/assets/images/blog/image-1.jpg',
title: 'Plan your next trip',
description: 'Traveling helps you explore new cultures, food, and make memories that last a lifetime.',
author: 'Alma Clark',
profile: '/assets/images/profile-3.jpeg',
date: '06 May',
slug: '/blog/3',
},
{
id: 4,
image: '/assets/images/blog/image-1.jpg',
title: 'My latest Vlog',
description: 'Check out my latest vlog where I share behind-the-scenes of my daily life and adventures.',
author: 'Alma Clark',
profile: '/assets/images/profile-4.jpeg',
date: '06 May',
slug: '/blog/4',
},
];
const Blog = () => {
return (
<div className="mt-10">
<h3 className="mb-6 text-xl font-bold md:text-3xl">Blogs</h3>
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 xl:grid-cols-4">
{/* ✅ First box: Create New Blog */}
<Link href="/create-blog" className="flex items-center justify-center space-y-5 rounded-md border border-dashed border-blue-500 bg-blue-50 p-5 text-center shadow hover:bg-blue-100 transition dark:border-blue-800 dark:bg-blue-900 dark:hover:bg-blue-800">
<div>
<div className="mb-3 text-5xl text-blue-600 dark:text-white">+</div>
<h5 className="text-lg font-semibold text-blue-800 dark:text-white">Create New Blog</h5>
</div>
</Link>
{blogs.map((blog) => (
<div
key={blog.id}
className="space-y-4 rounded-md border border-white-light bg-white p-5 shadow-[0px_0px_2px_0px_rgba(145,158,171,0.20),0px_12px_24px_-4px_rgba(145,158,171,0.12)] dark:border-[#1B2E4B] dark:bg-black"
>
<div className="max-h-56 overflow-hidden rounded-md">
<img src={blog.image} alt={blog.title} className="w-full object-cover" />
</div>
{/* ✅ Description first, then Title */}
<h5 className="text-lg font-semibold dark:text-white">{blog.title}</h5>
<p className="text-sm text-gray-600 dark:text-gray-400">{blog.description}</p>
{/*
<div className="flex items-center">
<div className="me-4 overflow-hidden rounded-full bg-white-dark">
<img src={blog.profile} className="h-11 w-11 object-cover" alt={blog.author} />
</div>
<div className="flex-1">
<h4 className="mb-1.5 font-semibold dark:text-white">{blog.author}</h4>
<p className="text-xs text-gray-500">{blog.date}</p>
</div>
</div> */}
{/* ✅ Read More button */}
<div>
<Link
href={blog.slug}
className="inline-block mt-3 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700"
>
Read More
</Link>
</div>
</div>
))}
</div>
</div>
);
};
export default Blog;

View File

@ -1,196 +0,0 @@
"use client";
import IconTrashLines from "@/components/icon/icon-trash-lines";
import React, { useState } from "react";
import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css";
// Custom toolbar options
const modules = {
toolbar: {
container: [
[{ header: [1, 2, 3, false] }],
["bold", "italic", "underline", "strike"],
[{ list: "ordered" }, { list: "bullet" }],
["blockquote", "code-block"],
[{ align: [] }],
["link", "image", "video"],
["clean"],
],
handlers: {
image: function () {
const input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/*");
input.click();
input.onchange = async () => {
const file = input.files?.[0];
if (file) {
const reader = new FileReader();
reader.onload = () => {
const quill = this.quill;
const range = quill.getSelection();
quill.insertEmbed(range.index, "image", reader.result);
};
reader.readAsDataURL(file);
}
};
},
},
},
};
const formats = [
"header",
"bold", "italic", "underline", "strike",
"blockquote", "code-block",
"list", "bullet",
"align",
"link", "image", "video",
];
const PostForm = () => {
const [formData, setFormData] = useState({
title: "",
slug: "",
coverImage: null as File | null,
description: "",
});
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
};
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0] || null;
setFormData((prev) => ({
...prev,
coverImage: file,
}));
};
const handleRemoveImage = () => {
setFormData((prev) => ({
...prev,
coverImage: null,
}));
};
const handleDescriptionChange = (value: string) => {
setFormData((prev) => ({
...prev,
description: value,
}));
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
const data = new FormData();
data.append("title", formData.title);
data.append("slug", formData.slug);
if (formData.coverImage) {
data.append("coverImage", formData.coverImage);
}
data.append("description", formData.description);
console.log("FormData prepared:", {
title: formData.title,
slug: formData.slug,
coverImage: formData.coverImage?.name,
description: formData.description,
});
};
return (
<form
onSubmit={handleSubmit}
className="space-y-5 max-w-4xl mx-auto p-6 bg-white rounded shadow-md"
>
<h2 className="text-xl font-bold mb-4">Create Blog</h2>
{/* Blog Title */}
<div>
<label className="block font-medium mb-1">Blog Title</label>
<input
type="text"
name="title"
value={formData.title}
onChange={handleChange}
placeholder="Enter blog title"
className="w-full border rounded-md px-3 py-2 focus:ring-2 focus:ring-blue-500 outline-none"
/>
</div>
{/* Slug */}
<div>
<label className="block font-medium mb-1">Slug</label>
<input
type="text"
name="slug"
value={formData.slug}
onChange={handleChange}
placeholder="Enter slug (e.g. my-first-blog)"
className="w-full border rounded-md px-3 py-2 focus:ring-2 focus:ring-green-500 outline-none"
/>
</div>
{/* Cover Image Upload */}
<div>
<label className="block font-medium mb-1">Cover Image</label>
<input
type="file"
accept="image/*"
onChange={handleImageChange}
className="w-full border rounded-md px-3 py-2 focus:ring-2 focus:ring-blue-500 outline-none"
/>
</div>
{/* Show Image Preview */}
{formData.coverImage && (
<div className="mt-3">
<p className="text-sm font-medium">Preview:</p>
<div className="relative inline-block mt-2">
<img
src={URL.createObjectURL(formData.coverImage)}
alt="Selected"
className="w-48 h-32 object-cover rounded border"
/>
<button
type="button"
onClick={handleRemoveImage}
className="absolute top-1 right-1 bg-red-600 text-white text-xs px-2 py-1 rounded hover:bg-red-700"
>
<IconTrashLines className="shrink-0" />
</button>
</div>
</div>
)}
{/* Description (ReactQuill) */}
<div className="mb-5">
<ReactQuill
value={formData.description}
onChange={handleDescriptionChange}
modules={modules}
formats={formats}
placeholder="Write your description..."
className="bg-white text-black rounded-md"
/>
</div>
{/* Submit Button */}
<button
type="submit"
className="bg-blue-600 text-white px-6 py-2 mt-5 rounded-md hover:bg-blue-700 transition"
>
Submit
</button>
</form>
);
};
export default PostForm;

View File

@ -249,36 +249,12 @@ const Sidebar = () => {
</ul>
</li>
<h2 className="-mx-4 mb-1 flex items-center bg-white-light/30 px-7 py-3 font-extrabold uppercase dark:bg-dark dark:bg-opacity-[0.08]">
{/* <h2 className="-mx-4 mb-1 flex items-center bg-white-light/30 px-7 py-3 font-extrabold uppercase dark:bg-dark dark:bg-opacity-[0.08]">
<IconMinus className="hidden h-5 w-4 flex-none" />
<span>{t('blog')}</span>
<span>{t('user_interface')}</span>
</h2>
<li className="menu nav-item">
<button type="button" className={`${currentMenu === 'blog' ? 'active' : ''} nav-link group w-full`} onClick={() => toggleMenu('blog')}>
<div className="flex items-center">
<IconMenuInvoice className="shrink-0 group-hover:!text-primary" />
<span className="text-black ltr:pl-3 rtl:pr-3 dark:text-[#506690] dark:group-hover:text-white-dark">{t('Blog')}</span>
</div>
<div className={currentMenu !== 'blog' ? '-rotate-90 rtl:rotate-90' : ''}>
<IconCaretDown />
</div>
</button>
<AnimateHeight duration={300} height={currentMenu === 'blog' ? 'auto' : 0}>
<ul className="sub-menu text-gray-500">
<li>
<Link href="/blog">{t('list')}</Link>
</li>
<li>
<Link href="/create-blog">{t('add')}</Link>
</li>
</ul>
</AnimateHeight>
</li>
{/* <li className="menu nav-item">
<button type="button" className={`${currentMenu === 'component' ? 'active' : ''} nav-link group w-full`} onClick={() => toggleMenu('component')}>
<div className="flex items-center">
<IconMenuComponents className="shrink-0 group-hover:!text-primary" />
@ -573,7 +549,7 @@ const Sidebar = () => {
</ul>
</AnimateHeight>
</li> */}
{/*
{/*
<h2 className="-mx-4 mb-1 flex items-center bg-white-light/30 px-7 py-3 font-extrabold uppercase dark:bg-dark dark:bg-opacity-[0.08]">
<IconMinus className="hidden h-5 w-4 flex-none" />
<span>{t('user_and_pages')}</span>

126
package-lock.json generated
View File

@ -28,7 +28,6 @@
"react-i18next": "^15.0.2",
"react-perfect-scrollbar": "^1.5.8",
"react-popper": "^2.3.0",
"react-quill": "^2.0.0",
"react-redux": "^9.1.2",
"sweetalert2": "^11.22.2",
"typescript": "^5.3.3",
@ -1064,15 +1063,6 @@
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
"integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA=="
},
"node_modules/@types/quill": {
"version": "1.3.10",
"resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz",
"integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==",
"license": "MIT",
"dependencies": {
"parchment": "^1.1.2"
}
},
"node_modules/@types/react": {
"version": "18.3.10",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.10.tgz",
@ -2051,15 +2041,6 @@
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
"node_modules/clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
"license": "MIT",
"engines": {
"node": ">=0.8"
}
},
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
@ -3153,29 +3134,11 @@
"node": ">=0.10.0"
}
},
"node_modules/eventemitter3": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==",
"license": "MIT"
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT"
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-diff": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==",
"license": "Apache-2.0"
},
"node_modules/fast-glob": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
@ -4852,12 +4815,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/parchment": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==",
"license": "BSD-3-Clause"
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@ -5314,74 +5271,6 @@
}
]
},
"node_modules/quill": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
"license": "BSD-3-Clause",
"dependencies": {
"clone": "^2.1.1",
"deep-equal": "^1.0.1",
"eventemitter3": "^2.0.3",
"extend": "^3.0.2",
"parchment": "^1.1.4",
"quill-delta": "^3.6.2"
}
},
"node_modules/quill-delta": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
"license": "MIT",
"dependencies": {
"deep-equal": "^1.0.1",
"extend": "^3.0.2",
"fast-diff": "1.1.2"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/quill-delta/node_modules/deep-equal": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
"integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
"license": "MIT",
"dependencies": {
"is-arguments": "^1.1.1",
"is-date-object": "^1.0.5",
"is-regex": "^1.1.4",
"object-is": "^1.1.5",
"object-keys": "^1.1.1",
"regexp.prototype.flags": "^1.5.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/quill/node_modules/deep-equal": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
"integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
"license": "MIT",
"dependencies": {
"is-arguments": "^1.1.1",
"is-date-object": "^1.0.5",
"is-regex": "^1.1.4",
"object-is": "^1.1.5",
"object-keys": "^1.1.1",
"regexp.prototype.flags": "^1.5.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
@ -5475,21 +5364,6 @@
"react-dom": "^16.8.0 || ^17 || ^18"
}
},
"node_modules/react-quill": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0.tgz",
"integrity": "sha512-4qQtv1FtCfLgoD3PXAur5RyxuUbPXQGOHgTlFie3jtxp43mXDtzCKaOgQ3mLyZfi1PUlyjycfivKelFhy13QUg==",
"license": "MIT",
"dependencies": {
"@types/quill": "^1.3.10",
"lodash": "^4.17.4",
"quill": "^1.3.7"
},
"peerDependencies": {
"react": "^16 || ^17 || ^18",
"react-dom": "^16 || ^17 || ^18"
}
},
"node_modules/react-redux": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",

View File

@ -29,7 +29,6 @@
"react-i18next": "^15.0.2",
"react-perfect-scrollbar": "^1.5.8",
"react-popper": "^2.3.0",
"react-quill": "^2.0.0",
"react-redux": "^9.1.2",
"sweetalert2": "^11.22.2",
"typescript": "^5.3.3",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB