Compare commits
11 Commits
edac2c32a3
...
373402eb1b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
373402eb1b | ||
|
|
2c0a585bf8 | ||
|
|
240bc7ccfb | ||
|
|
ae33539f72 | ||
|
|
6c834607bd | ||
| b14a3189b4 | |||
|
|
027d1090df | ||
|
|
9bcf1fb0eb | ||
|
|
d98bc7bbb0 | ||
|
|
4f101885a8 | ||
| dbec761a0b |
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 parsa aghayi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
168
app/Http/Controllers/Blog/CategoryController.php
Normal file
@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Blog;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\CategoryResource;
|
||||
use App\Http\Resources\PostResource;
|
||||
use App\Models\Blog\Category;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
// نمایش لیست دستهبندیها با صفحهبندی
|
||||
public function index(Request $request)
|
||||
{
|
||||
// گرفتن فیلتر و سورت از درخواست کاربر
|
||||
$filter = $request->input('filter'); // فیلتر (به عنوان مثال، نام دستهبندی)
|
||||
$sortBy = $request->input('sort_by', 'created_at'); // مرتبسازی (پیشفرض بر اساس زمان ایجاد)
|
||||
$sortDirection = $request->input('sort_direction', 'desc'); // جهت مرتبسازی (پیشفرض نزولی)
|
||||
$perPage = $request->input('per_page', 10); // تعداد آیتمها در هر صفحه (پیشفرض ۱۰)
|
||||
|
||||
// شروع کوئری با مدل دستهبندی و روابط
|
||||
$query = Category::with('posts');
|
||||
|
||||
// اعمال فیلتر در صورت موجود بودن
|
||||
if (!empty($filter)) {
|
||||
$query->where('name', 'like', '%' . $filter . '%');
|
||||
}
|
||||
|
||||
// اعمال مرتبسازی
|
||||
$query->orderBy($sortBy, $sortDirection);
|
||||
|
||||
// گرفتن نتایج با پجینیشن
|
||||
$categories = $query->paginate($perPage);
|
||||
|
||||
// بازگشت دادهها با استفاده از ریسورس
|
||||
return CategoryResource::collection($categories);
|
||||
}
|
||||
|
||||
// نمایش یک دستهبندی خاص
|
||||
public function show($id)
|
||||
{
|
||||
$category = Category::with('posts')->findOrFail($id);
|
||||
return new CategoryResource($category);
|
||||
}
|
||||
|
||||
/**
|
||||
* نمایش دستهبندی و پستهای مرتبط با آن بر اساس slug
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $slug
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getCategoryWithPosts(Request $request, $slug)
|
||||
{
|
||||
// یافتن دستهبندی بر اساس slug
|
||||
$category = Category::where('slug', $slug)->first();
|
||||
|
||||
if (!$category) {
|
||||
return response()->json([
|
||||
'message' => 'دستهبندی مورد نظر یافت نشد.'
|
||||
], 404);
|
||||
}
|
||||
|
||||
// دریافت تعداد پستها در هر صفحه (پیشفرض: ۱۰)
|
||||
$perPage = $request->input('per_page', 10);
|
||||
|
||||
// دریافت فیلتر و سورت از درخواست
|
||||
$filter = $request->input('filter'); // فیلتر (به عنوان مثال، عنوان پست)
|
||||
$sortBy = $request->input('sort_by', 'published_at'); // مرتبسازی (پیشفرض بر اساس تاریخ انتشار)
|
||||
$sortDirection = $request->input('sort_direction', 'desc'); // جهت مرتبسازی (پیشفرض نزولی)
|
||||
|
||||
// شروع کوئری با پستهای مربوط به دستهبندی
|
||||
$postsQuery = $category->posts()->with(['category', 'tags', 'author']);
|
||||
|
||||
// اعمال فیلتر در صورت موجود بودن
|
||||
if (!empty($filter)) {
|
||||
$postsQuery->where('title', 'like', '%' . $filter . '%');
|
||||
}
|
||||
|
||||
// اعمال مرتبسازی
|
||||
$postsQuery->orderBy($sortBy, $sortDirection);
|
||||
|
||||
// گرفتن پستها با پجینیشن
|
||||
$posts = $postsQuery->paginate($perPage);
|
||||
|
||||
// ساخت meta و links برای pagination
|
||||
$meta = [
|
||||
'total' => $posts->total(),
|
||||
'per_page' => $posts->perPage(),
|
||||
'current_page' => $posts->currentPage(),
|
||||
'last_page' => $posts->lastPage(),
|
||||
'from' => $posts->firstItem(),
|
||||
'to' => $posts->lastItem(),
|
||||
];
|
||||
|
||||
$links = [
|
||||
'first' => $posts->url(1),
|
||||
'last' => $posts->url($posts->lastPage()),
|
||||
'prev' => $posts->previousPageUrl(),
|
||||
'next' => $posts->nextPageUrl(),
|
||||
];
|
||||
|
||||
// بازگشت اطلاعات دستهبندی و پستها
|
||||
return response()->json([
|
||||
'category' => new CategoryResource($category),
|
||||
'posts' => PostResource::collection($posts),
|
||||
'meta' => $meta,
|
||||
'links' => $links,
|
||||
], 200);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ذخیره یک دستهبندی جدید
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'name' => 'required|string|max:255|unique:categories,name',
|
||||
'slug' => 'required|string|unique:categories,slug',
|
||||
'description' => 'required|string',
|
||||
'short_description' => 'nullable|string|max:500',
|
||||
'image' => 'nullable|url',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json($validator->errors(), 422);
|
||||
}
|
||||
|
||||
$category = Category::create($validator->validated());
|
||||
|
||||
return new CategoryResource($category);
|
||||
}
|
||||
|
||||
// بهروزرسانی یک دستهبندی خاص
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$category = Category::findOrFail($id);
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'name' => 'sometimes|required|string|max:255|unique:categories,name,' . $category->id,
|
||||
'slug' => 'sometimes|required|string|unique:categories,slug,' . $category->id,
|
||||
'description' => 'sometimes|required|string',
|
||||
'short_description' => 'nullable|string|max:500',
|
||||
'image' => 'nullable|url',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json($validator->errors(), 422);
|
||||
}
|
||||
|
||||
$category->update($validator->validated());
|
||||
|
||||
return new CategoryResource($category);
|
||||
}
|
||||
|
||||
// حذف یک دستهبندی خاص
|
||||
public function destroy($id)
|
||||
{
|
||||
$category = Category::findOrFail($id);
|
||||
// قبل از حذف، مطمئن شوید که پستها به دستهبندی دیگری منتقل شدهاند یا حذف شوند
|
||||
// برای سادگی، اینجا فقط دستهبندی را حذف میکنیم
|
||||
$category->delete();
|
||||
|
||||
return response()->json(['message' => 'Category deleted successfully'], 200);
|
||||
}
|
||||
}
|
||||
52
app/Http/Controllers/Blog/HomeController.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Blog;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\CategoryResource;
|
||||
use App\Http\Resources\PostResource;
|
||||
use App\Models\Blog\Category;
|
||||
use App\Models\Blog\Post;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
/**
|
||||
* برگرداندن دادههای مورد نیاز برای صفحهی اصلی
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
// 1. 5 پست آخر
|
||||
$latestPosts = Post::with(['category', 'tags', 'author'])
|
||||
->orderBy('published_at', 'desc')
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
// 2. 5 دستهبندی آخر
|
||||
$latestCategories = Category::orderBy('created_at', 'desc')
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
// 3. 5 پست با بیشترین بازدید
|
||||
$mostViewedPosts = Post::with(['category', 'tags', 'author'])
|
||||
->orderBy('views', 'desc')
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
// 4. 4 پست تصادفی
|
||||
$randomPosts = Post::with(['category', 'tags', 'author'])
|
||||
->inRandomOrder()
|
||||
->take(4)
|
||||
->get();
|
||||
|
||||
// بازگشت به صورت JSON با استفاده از منابع (Resources)
|
||||
return response()->json([
|
||||
'latest_posts' => PostResource::collection($latestPosts),
|
||||
'latest_categories' => CategoryResource::collection($latestCategories),
|
||||
'most_viewed_posts' => PostResource::collection($mostViewedPosts),
|
||||
'random_posts' => PostResource::collection($randomPosts),
|
||||
], 200);
|
||||
}
|
||||
}
|
||||
127
app/Http/Controllers/Blog/PostController.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Blog;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\PostResource;
|
||||
use App\Models\Blog\Post;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class PostController extends Controller
|
||||
{
|
||||
// نمایش لیست پستها با فیلتر و صفحهبندی
|
||||
public function index(Request $request)
|
||||
{
|
||||
// دریافت پارامترهای فیلتر از درخواست
|
||||
$filters = $request->only(['category', 'tag', 'search', 'author', 'published']);
|
||||
|
||||
// دریافت پارامترهای مرتبسازی از درخواست
|
||||
$sortField = $request->get('sort_field', 'published_at'); // فیلد پیشفرض: published_at
|
||||
$sortDirection = $request->get('sort_direction', 'desc'); // جهت پیشفرض: نزولی
|
||||
|
||||
// دریافت پارامترهای صفحهبندی از درخواست
|
||||
$perPage = $request->get('per_page', 10); // تعداد آیتمها در هر صفحه (پیشفرض: ۱۰)
|
||||
|
||||
// ساخت Query با اعمال فیلترها و مرتبسازی
|
||||
$query = Post::with(['category', 'tags', 'author'])
|
||||
->filter($filters)
|
||||
->sort($sortField, $sortDirection);
|
||||
|
||||
// اعمال صفحهبندی
|
||||
$posts = $query->paginate($perPage);
|
||||
|
||||
// بازگشت نتایج به صورت JSON با استفاده از Resource
|
||||
return PostResource::collection($posts);
|
||||
}
|
||||
|
||||
// نمایش یک پست خاص
|
||||
public function show($slug)
|
||||
{
|
||||
// یافتن پست بر اساس slug و بارگذاری روابط مرتبط
|
||||
$post = Post::with(['category', 'tags', 'author', 'relatedPosts.category', 'relatedPosts.tags', 'relatedPosts.author'])
|
||||
->where('slug', $slug)
|
||||
->firstOrFail(); // در صورت عدم وجود پست، خطای 404 برمیگرداند
|
||||
|
||||
// بازگشت پست و پستهای مرتبط به صورت JSON با استفاده از منابع
|
||||
return response()->json([
|
||||
'post' => new PostResource($post),
|
||||
'related_posts' => PostResource::collection($post->relatedPosts->sortByDesc('published_at')->take(5)), // بازگشت ۵ پست مرتبط جدیدترین
|
||||
], 200);
|
||||
}
|
||||
|
||||
// ذخیره یک پست جدید
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'title' => 'required|string|max:255',
|
||||
'body' => 'required|string',
|
||||
'excerpt' => 'nullable|string|max:500',
|
||||
'slug' => 'required|string|unique:posts,slug',
|
||||
'author_id' => 'required|exists:users,id',
|
||||
'category_id' => 'required|exists:categories,id',
|
||||
'featured_image' => 'nullable|url',
|
||||
'views' => 'nullable|integer',
|
||||
'likes' => 'nullable|integer',
|
||||
'published_at' => 'nullable|date',
|
||||
'tags' => 'nullable|array',
|
||||
'tags.*' => 'exists:tags,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json($validator->errors(), 422);
|
||||
}
|
||||
|
||||
$post = Post::create($validator->validated());
|
||||
|
||||
if ($request->has('tags')) {
|
||||
$post->tags()->attach($request->tags);
|
||||
}
|
||||
|
||||
return new PostResource($post->load(['category', 'tags', 'author']));
|
||||
}
|
||||
|
||||
// بهروزرسانی یک پست خاص
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$post = Post::findOrFail($id);
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'title' => 'sometimes|required|string|max:255',
|
||||
'body' => 'sometimes|required|string',
|
||||
'excerpt' => 'nullable|string|max:500',
|
||||
'slug' => 'sometimes|required|string|unique:posts,slug,' . $post->id,
|
||||
'author_id' => 'sometimes|required|exists:users,id',
|
||||
'category_id' => 'sometimes|required|exists:categories,id',
|
||||
'featured_image' => 'nullable|url',
|
||||
'views' => 'nullable|integer',
|
||||
'likes' => 'nullable|integer',
|
||||
'published_at' => 'nullable|date',
|
||||
'tags' => 'nullable|array',
|
||||
'tags.*' => 'exists:tags,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json($validator->errors(), 422);
|
||||
}
|
||||
|
||||
$post->update($validator->validated());
|
||||
|
||||
if ($request->has('tags')) {
|
||||
$post->tags()->sync($request->tags);
|
||||
}
|
||||
|
||||
return new PostResource($post->load(['category', 'tags', 'author']));
|
||||
}
|
||||
|
||||
// حذف یک پست خاص
|
||||
public function destroy($id)
|
||||
{
|
||||
$post = Post::findOrFail($id);
|
||||
$post->tags()->detach();
|
||||
$post->relatedPosts()->detach();
|
||||
$post->delete();
|
||||
|
||||
return response()->json(['message' => 'Post deleted successfully'], 200);
|
||||
}
|
||||
}
|
||||
72
app/Http/Controllers/Blog/TagController.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Blog;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\TagResource;
|
||||
use App\Models\Blog\Tag;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class TagController extends Controller
|
||||
{
|
||||
// نمایش لیست تگها با صفحهبندی
|
||||
public function index(Request $request)
|
||||
{
|
||||
$tags = Tag::with('posts')->paginate(10);
|
||||
return TagResource::collection($tags);
|
||||
}
|
||||
|
||||
// نمایش یک تگ خاص
|
||||
public function show($id)
|
||||
{
|
||||
$tag = Tag::with('posts')->findOrFail($id);
|
||||
return new TagResource($tag);
|
||||
}
|
||||
|
||||
// ذخیره یک تگ جدید
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'name' => 'required|string|max:255|unique:tags,name',
|
||||
'slug' => 'required|string|unique:tags,slug',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json($validator->errors(), 422);
|
||||
}
|
||||
|
||||
$tag = Tag::create($validator->validated());
|
||||
|
||||
return new TagResource($tag);
|
||||
}
|
||||
|
||||
// بهروزرسانی یک تگ خاص
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$tag = Tag::findOrFail($id);
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'name' => 'sometimes|required|string|max:255|unique:tags,name,' . $tag->id,
|
||||
'slug' => 'sometimes|required|string|unique:tags,slug,' . $tag->id,
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json($validator->errors(), 422);
|
||||
}
|
||||
|
||||
$tag->update($validator->validated());
|
||||
|
||||
return new TagResource($tag);
|
||||
}
|
||||
|
||||
// حذف یک تگ خاص
|
||||
public function destroy($id)
|
||||
{
|
||||
$tag = Tag::findOrFail($id);
|
||||
$tag->posts()->detach();
|
||||
$tag->delete();
|
||||
|
||||
return response()->json(['message' => 'Tag deleted successfully'], 200);
|
||||
}
|
||||
}
|
||||
82
app/Http/Controllers/Website/AboutMeController.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Website;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Website\AboutMe;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class AboutMeController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$aboutMe = AboutMe::with('skills.translations')->first(); // بارگذاری مهارتها و ترجمهها
|
||||
return response()->json($aboutMe);
|
||||
}
|
||||
|
||||
public function show($id)
|
||||
{
|
||||
$aboutMe = AboutMe::with('skills.translations')->findOrFail($id);
|
||||
return response()->json($aboutMe);
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$aboutMe = AboutMe::create($request->all());
|
||||
return response()->json($aboutMe, 201);
|
||||
}
|
||||
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$aboutMe = AboutMe::findOrFail($id);
|
||||
$aboutMe->update($request->all());
|
||||
return response()->json($aboutMe);
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
AboutMe::destroy($id);
|
||||
return response()->json(null, 204);
|
||||
}
|
||||
|
||||
// متد جدید برای دریافت ترجمه بر اساس locale از کوکی
|
||||
public function getTranslation($id, $locale)
|
||||
{
|
||||
// بارگذاری AboutMe با ترجمههای مربوط به locale و مهارتها
|
||||
$aboutMe = AboutMe::with(['translations' => function ($query) use ($locale) {
|
||||
$query->where('locale', $locale);
|
||||
}, 'skills.translations' => function ($query) use ($locale) {
|
||||
$query->where('locale', $locale);
|
||||
}])->findOrFail($id);
|
||||
|
||||
// اگر ترجمه موجود نیست، میتوانید ترجمه پیشفرض یا خطا را برگردانید
|
||||
if ($aboutMe->translations->isEmpty()) {
|
||||
return response()->json(['message' => 'Translation not found', 'locale' => $locale], 404);
|
||||
}
|
||||
|
||||
// ترکیب اطلاعات AboutMe و ترجمه
|
||||
$translation = $aboutMe->translations->first(); // فقط یک ترجمه دریافت میکنیم
|
||||
$skills = $aboutMe->skills->map(function ($skill) use ($locale) {
|
||||
$translation = $skill->getTranslation($locale); // گرفتن ترجمه برای هر مهارت
|
||||
|
||||
return [
|
||||
'id' => $skill->id,
|
||||
'title' => $translation ? $translation->title : null, // عنوان از ترجمه
|
||||
'description' => $translation ? $translation->description : null, // توضیحات از ترجمه
|
||||
'image' => $skill->image, // تصویر
|
||||
'link' => $skill->link, // لینک
|
||||
'percentage' => $skill->percentage, // درصد
|
||||
];
|
||||
});
|
||||
|
||||
$data = [
|
||||
'id' => $aboutMe->id,
|
||||
'title' => $translation->title,
|
||||
'description' => $translation->description,
|
||||
'image' => $aboutMe->image,
|
||||
'skills' => $skills, // مهارتها اکنون بارگذاری شدهاند
|
||||
];
|
||||
|
||||
return response()->json($data);
|
||||
}
|
||||
}
|
||||
119
app/Http/Controllers/Website/ProjectController.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\website;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Website\Project;
|
||||
use App\Models\Website\ProjectCategory;
|
||||
|
||||
class ProjectController extends Controller
|
||||
{
|
||||
public function index($locale): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
// Read per_page from query string or set a default value
|
||||
$perPage = request()->query('per_page', 10); // مقدار پیشفرض ۱۰ در نظر گرفته میشود
|
||||
|
||||
// Retrieve projects with translations and categories
|
||||
$projects = Project::with('translations', 'category.translations')->paginate($perPage);
|
||||
$formattedProjects = $projects->items();
|
||||
|
||||
$formattedProjects = array_map(function ($project) use ($locale) {
|
||||
$translation = $project->translations->firstWhere('locale', $locale);
|
||||
$categoryTranslation = $project->category->translations->firstWhere('locale', $locale);
|
||||
|
||||
return [
|
||||
'id' => $project->id,
|
||||
'title' => $translation ? $translation->title : null,
|
||||
'category' => $categoryTranslation ? $categoryTranslation->title : null,
|
||||
'images' => [
|
||||
['src' => $project->image1, 'position' => '1', 'zIndex' => 1],
|
||||
['src' => $project->image2, 'position' => '2', 'zIndex' => 2],
|
||||
],
|
||||
'created_at' => $project->created_at,
|
||||
'updated_at' => $project->updated_at,
|
||||
];
|
||||
}, $formattedProjects);
|
||||
|
||||
return response()->json([
|
||||
'projects' => [
|
||||
'current_page' => $projects->currentPage(),
|
||||
'data' => $formattedProjects,
|
||||
'total' => $projects->total(),
|
||||
'last_page' => $projects->lastPage(),
|
||||
],
|
||||
'categories' => ProjectCategory::all()->map(function ($category) use ($locale) {
|
||||
return [
|
||||
'id' => $category->id,
|
||||
'title' => $category->translations->firstWhere('locale', $locale)->title ?? null,
|
||||
'image' => $category->image,
|
||||
];
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$project = Project::create($request->only(['category_id', 'image1', 'image2']));
|
||||
|
||||
// ایجاد ترجمهها
|
||||
foreach (['fa', 'en'] as $locale) {
|
||||
$project->translations()->create([
|
||||
'locale' => $locale,
|
||||
'title' => $request->input("title_$locale"),
|
||||
'description' => $request->input("description_$locale"),
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json($project->load('translations'), 201);
|
||||
}
|
||||
|
||||
public function show($id)
|
||||
{
|
||||
$project = Project::with('translations', 'category.translations')->findOrFail($id);
|
||||
|
||||
$translation = $project->translations->firstWhere('locale', 'fa');
|
||||
$categoryTranslation = $project->category->translations->firstWhere('locale', 'fa');
|
||||
|
||||
$formattedProject = [
|
||||
'id' => $project->id,
|
||||
'title' => $translation ? $translation->title : null,
|
||||
'category' => $categoryTranslation ? $categoryTranslation->title : null,
|
||||
'images' => [
|
||||
['src' => $project->image1, 'position' => '1', 'zIndex' => 1],
|
||||
['src' => $project->image2, 'position' => '2', 'zIndex' => 2],
|
||||
],
|
||||
'created_at' => $project->created_at,
|
||||
'updated_at' => $project->updated_at,
|
||||
];
|
||||
|
||||
return response()->json(['project' => $formattedProject]);
|
||||
}
|
||||
|
||||
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$project = Project::findOrFail($id);
|
||||
$project->update($request->only(['category_id', 'image1', 'image2']));
|
||||
|
||||
// بهروزرسانی ترجمهها
|
||||
foreach (['fa', 'en'] as $locale) {
|
||||
$project->translations()->updateOrCreate(
|
||||
['locale' => $locale],
|
||||
[
|
||||
'title' => $request->input("title_$locale"),
|
||||
'description' => $request->input("description_$locale"),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return response()->json($project->load('translations'));
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
Project::destroy($id);
|
||||
return response()->json(null, 204);
|
||||
}
|
||||
}
|
||||
50
app/Http/Controllers/Website/ServiceController.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Website;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Website\Service;
|
||||
|
||||
class ServiceController extends Controller
|
||||
{
|
||||
/**
|
||||
* دریافت لیست خدمات با ترجمهها بر اساس زبان
|
||||
*/
|
||||
public function index($locale)
|
||||
{
|
||||
// گرفتن همه خدمات به همراه ترجمهها
|
||||
$services = Service::with(['translations' => function ($query) use ($locale) {
|
||||
$query->where('locale', $locale);
|
||||
}])->get();
|
||||
|
||||
// فرمتی که میخواهیم به کاربر ارسال کنیم
|
||||
$response = $services->map(function ($service) use ($locale) {
|
||||
return [
|
||||
'id' => $service->id,
|
||||
'imageSrc' => $service->imageSrc,
|
||||
'altText' => $service->translations->first()->altText ?? '',
|
||||
'created_at' => $service->created_at,
|
||||
'updated_at' => $service->updated_at,
|
||||
'title' => optional($service->translations->first())->title,
|
||||
'description' => optional($service->translations->first())->description,
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* نمایش یک خدمت خاص با ترجمه
|
||||
*/
|
||||
public function showTranslation($id, $locale)
|
||||
{
|
||||
$service = Service::with('translations')->findOrFail($id);
|
||||
|
||||
return response()->json([
|
||||
'id' => $service->id,
|
||||
'imageSrc' => $service->imageSrc,
|
||||
'title' => $service->getTitle($locale),
|
||||
'description' => $service->getDescription($locale),
|
||||
]);
|
||||
}
|
||||
}
|
||||
32
app/Http/Resources/CategoryResource.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class CategoryResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'slug' => $this->slug,
|
||||
'description' => $this->description,
|
||||
'short_description' => $this->short_description,
|
||||
'image' => $this->image,
|
||||
'posts_count' => $this->whenLoaded('posts', function () {
|
||||
return $this->posts->count();
|
||||
}),
|
||||
'created_at' => Carbon::parse($this->created_at)->format('M d Y'),
|
||||
'updated_at' => Carbon::parse($this->updated_at)->format('M d Y'),
|
||||
];
|
||||
}
|
||||
}
|
||||
35
app/Http/Resources/PostResource.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class PostResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'title' => $this->title,
|
||||
'slug' => $this->slug,
|
||||
'excerpt' => $this->excerpt,
|
||||
'body' => $this->body,
|
||||
'author' => new UserResource($this->author),
|
||||
'category' => new CategoryResource($this->category),
|
||||
'tags' => TagResource::collection($this->tags),
|
||||
'featured_image' => $this->featured_image,
|
||||
'views' => $this->views,
|
||||
'likes' => $this->likes,
|
||||
'published_at' => $this->published_at,
|
||||
'created_at' => Carbon::parse($this->created_at)->format('M d Y'),
|
||||
'updated_at' => Carbon::parse($this->updated_at)->format('M d Y'),
|
||||
];
|
||||
}
|
||||
}
|
||||
29
app/Http/Resources/TagResource.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TagResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'slug' => $this->slug,
|
||||
'posts_count' => $this->whenLoaded('posts', function () {
|
||||
return $this->posts->count();
|
||||
}),
|
||||
'created_at' => Carbon::parse($this->created_at)->format('M d Y'),
|
||||
'updated_at' => Carbon::parse($this->updated_at)->format('M d Y'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,12 @@ class User extends ResourceCollection
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return parent::toArray($request);
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
// اضافه کردن سایر فیلدهای مورد نیاز
|
||||
'email' => $this->email,
|
||||
'created_at' => $this->created_at,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
@ -18,8 +19,8 @@ public function toArray(Request $request): array
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'email' => $this->email,
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
'created_at' => Carbon::parse($this->created_at)->format('M d Y'),
|
||||
'updated_at' => Carbon::parse($this->updated_at)->format('M d Y'),
|
||||
];
|
||||
}
|
||||
}
|
||||
25
app/Models/Blog/Category.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Blog;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Category extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'slug',
|
||||
'description',
|
||||
'short_description',
|
||||
'image',
|
||||
];
|
||||
|
||||
// رابطه با پستها
|
||||
public function posts()
|
||||
{
|
||||
return $this->hasMany(Post::class);
|
||||
}
|
||||
}
|
||||
99
app/Models/Blog/Post.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Blog;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Models\User;
|
||||
|
||||
class Post extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'body',
|
||||
'excerpt',
|
||||
'slug',
|
||||
'author_id',
|
||||
'category_id',
|
||||
'featured_image',
|
||||
'views',
|
||||
'likes',
|
||||
'published_at',
|
||||
];
|
||||
|
||||
// رابطه با نویسنده
|
||||
public function author()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'author_id');
|
||||
}
|
||||
|
||||
// رابطه با دستهبندی
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo(Category::class);
|
||||
}
|
||||
|
||||
// رابطه با تگها
|
||||
public function tags()
|
||||
{
|
||||
return $this->belongsToMany(Tag::class)->withTimestamps();
|
||||
}
|
||||
|
||||
// پستهای مرتبط
|
||||
public function relatedPosts()
|
||||
{
|
||||
return $this->belongsToMany(Post::class, 'related_posts', 'post_id', 'related_post_id')->withTimestamps();
|
||||
}
|
||||
|
||||
// اسکوپ فیلتر
|
||||
public function scopeFilter($query, $filters)
|
||||
{
|
||||
if (isset($filters['category'])) {
|
||||
$query->whereHas('category', function ($q) use ($filters) {
|
||||
$q->where('slug', $filters['category']);
|
||||
});
|
||||
}
|
||||
|
||||
if (isset($filters['tag'])) {
|
||||
$query->whereHas('tags', function ($q) use ($filters) {
|
||||
$q->where('slug', $filters['tag']);
|
||||
});
|
||||
}
|
||||
|
||||
if (isset($filters['search'])) {
|
||||
$query->where(function ($q) use ($filters) {
|
||||
$q->where('title', 'like', '%' . $filters['search'] . '%')
|
||||
->orWhere('body', 'like', '%' . $filters['search'] . '%');
|
||||
});
|
||||
}
|
||||
|
||||
if (isset($filters['author'])) {
|
||||
$query->whereHas('author', function ($q) use ($filters) {
|
||||
$q->where('id', $filters['author']);
|
||||
});
|
||||
}
|
||||
|
||||
if (isset($filters['published'])) {
|
||||
$query->whereNotNull('published_at');
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope برای اعمال مرتبسازی
|
||||
*/
|
||||
public function scopeSort($query, $sortField, $sortDirection = 'asc')
|
||||
{
|
||||
// بررسی اینکه فیلد مرتبسازی معتبر است یا خیر
|
||||
$allowedSortFields = ['published_at', 'views', 'likes', 'title'];
|
||||
if (in_array($sortField, $allowedSortFields)) {
|
||||
$sortDirection = strtolower($sortDirection) === 'desc' ? 'desc' : 'asc';
|
||||
$query->orderBy($sortField, $sortDirection);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
22
app/Models/Blog/Tag.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Blog;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Tag extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'slug',
|
||||
];
|
||||
|
||||
// رابطه با پستها
|
||||
public function posts()
|
||||
{
|
||||
return $this->belongsToMany(Post::class)->withTimestamps();
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,8 @@
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
|
||||
use App\Models\Blog\Post;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
@ -44,4 +46,9 @@ protected function casts(): array
|
||||
'password' => 'hashed',
|
||||
];
|
||||
}
|
||||
|
||||
public function posts()
|
||||
{
|
||||
return $this->hasMany(Post::class, 'author_id');
|
||||
}
|
||||
}
|
||||
|
||||
53
app/Models/Website/AboutMe.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Website;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AboutMe extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'website_about_me';
|
||||
protected $fillable = ['image'];
|
||||
|
||||
/**
|
||||
* ارتباط با ترجمهها
|
||||
*/
|
||||
public function translations()
|
||||
{
|
||||
return $this->hasMany(AboutMeTranslation::class, 'about_me_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* گرفتن ترجمه بر اساس زبان فعلی
|
||||
*/
|
||||
public function getTranslation($locale)
|
||||
{
|
||||
return $this->translations()->where('locale', $locale)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* گرفتن عنوان بر اساس زبان فعلی
|
||||
*/
|
||||
public function getTitle($locale)
|
||||
{
|
||||
$translation = $this->getTranslation($locale);
|
||||
return $translation ? $translation->title : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* گرفتن توضیحات بر اساس زبان فعلی
|
||||
*/
|
||||
public function getDescription($locale)
|
||||
{
|
||||
$translation = $this->getTranslation($locale);
|
||||
return $translation ? $translation->description : null;
|
||||
}
|
||||
|
||||
public function skills()
|
||||
{
|
||||
return $this->hasMany(Skill::class);
|
||||
}
|
||||
}
|
||||
22
app/Models/Website/AboutMeTranslation.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Website;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AboutMeTranslation extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'website_about_me_translations';
|
||||
protected $fillable = ['about_me_id', 'locale', 'title', 'description'];
|
||||
|
||||
/**
|
||||
* ارتباط با AboutMe
|
||||
*/
|
||||
public function aboutMe()
|
||||
{
|
||||
return $this->belongsTo(AboutMe::class, 'about_me_id');
|
||||
}
|
||||
}
|
||||
24
app/Models/Website/Project.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Website;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Project extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'website_projects'; // نام صحیح جدول
|
||||
protected $fillable = ['category_id', 'image1', 'image2'];
|
||||
|
||||
public function translations()
|
||||
{
|
||||
return $this->hasMany(ProjectTranslation::class, 'project_id');
|
||||
}
|
||||
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo(ProjectCategory::class, 'category_id');
|
||||
}
|
||||
}
|
||||
19
app/Models/Website/ProjectCategory.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Website;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ProjectCategory extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'website_project_categories'; // نام صحیح جدول
|
||||
protected $fillable = ['image'];
|
||||
|
||||
public function translations()
|
||||
{
|
||||
return $this->hasMany(ProjectCategoryTranslation::class, 'category_id');
|
||||
}
|
||||
}
|
||||
14
app/Models/Website/ProjectCategoryTranslation.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Website;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ProjectCategoryTranslation extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'website_project_category_translations'; // نام صحیح جدول
|
||||
protected $fillable = ['category_id', 'locale', 'title', 'description'];
|
||||
}
|
||||
19
app/Models/Website/ProjectTranslation.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Website;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ProjectTranslation extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'website_project_translations'; // نام صحیح جدول
|
||||
protected $fillable = ['project_id', 'locale', 'title', 'description'];
|
||||
|
||||
public function project()
|
||||
{
|
||||
return $this->belongsTo(Project::class, 'project_id');
|
||||
}
|
||||
}
|
||||
48
app/Models/Website/Service.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Website;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Service extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'website_services'; // نام جدول
|
||||
protected $fillable = ['imageSrc']; // فیلدهایی که قابل پر کردن هستند
|
||||
|
||||
/**
|
||||
* ارتباط با جدول ترجمهها
|
||||
*/
|
||||
public function translations()
|
||||
{
|
||||
return $this->hasMany(ServiceTranslation::class, 'service_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* گرفتن ترجمه بر اساس زبان فعلی
|
||||
*/
|
||||
public function getTranslation($locale)
|
||||
{
|
||||
return $this->translations()->where('locale', $locale)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* گرفتن عنوان بر اساس زبان فعلی
|
||||
*/
|
||||
public function getTitle($locale)
|
||||
{
|
||||
$translation = $this->getTranslation($locale);
|
||||
return $translation ? $translation->title : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* گرفتن توضیحات بر اساس زبان فعلی
|
||||
*/
|
||||
public function getDescription($locale)
|
||||
{
|
||||
$translation = $this->getTranslation($locale);
|
||||
return $translation ? $translation->description : null;
|
||||
}
|
||||
}
|
||||
22
app/Models/Website/ServiceTranslation.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Website;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ServiceTranslation extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'website_service_translations'; // نام جدول
|
||||
protected $fillable = ['service_id', 'locale', 'title', 'description']; // فیلدهایی که قابل پر کردن هستند
|
||||
|
||||
/**
|
||||
* ارتباط با جدول خدمات
|
||||
*/
|
||||
public function service()
|
||||
{
|
||||
return $this->belongsTo(Service::class, 'service_id');
|
||||
}
|
||||
}
|
||||
56
app/Models/Website/Skill.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Website;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Skill extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'website_skills'; // نام جدول
|
||||
protected $fillable = ['image', 'link', 'about_me_id', 'percentage']; // فیلدهایی که قابل پر کردن هستند
|
||||
|
||||
/**
|
||||
* ارتباط با جدول AboutMe
|
||||
*/
|
||||
public function aboutMe()
|
||||
{
|
||||
return $this->belongsTo(AboutMe::class, 'about_me_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* ارتباط با جدول ترجمهها
|
||||
*/
|
||||
public function translations()
|
||||
{
|
||||
return $this->hasMany(SkillTranslation::class, 'skill_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* گرفتن ترجمه بر اساس زبان فعلی
|
||||
*/
|
||||
public function getTranslation($locale)
|
||||
{
|
||||
return $this->translations()->where('locale', $locale)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* گرفتن عنوان بر اساس زبان فعلی
|
||||
*/
|
||||
public function getTitle($locale)
|
||||
{
|
||||
$translation = $this->getTranslation($locale);
|
||||
return $translation ? $translation->title : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* گرفتن توضیحات بر اساس زبان فعلی
|
||||
*/
|
||||
public function getDescription($locale)
|
||||
{
|
||||
$translation = $this->getTranslation($locale);
|
||||
return $translation ? $translation->description : null;
|
||||
}
|
||||
}
|
||||
22
app/Models/Website/SkillTranslation.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Website;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SkillTranslation extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'website_skill_translations'; // نام جدول
|
||||
protected $fillable = ['skill_id', 'locale', 'title', 'description']; // فیلدهایی که قابل پر کردن هستند
|
||||
|
||||
/**
|
||||
* ارتباط با جدول Skills
|
||||
*/
|
||||
public function skill()
|
||||
{
|
||||
return $this->belongsTo(Skill::class, 'skill_id');
|
||||
}
|
||||
}
|
||||
BIN
backend.zip
0
bootstrap/cache/.gitignore
vendored
Normal file → Executable file
34
config/cors.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross-Origin Resource Sharing (CORS) Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure your settings for cross-origin resource sharing
|
||||
| or "CORS". This determines what cross-origin operations may execute
|
||||
| in web browsers. You are free to adjust these settings as needed.
|
||||
|
|
||||
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||
|
|
||||
*/
|
||||
|
||||
'paths' => ['api/*', 'sanctum/csrf-cookie'],
|
||||
|
||||
'allowed_methods' => ['*'],
|
||||
|
||||
'allowed_origins' => ['*'],
|
||||
|
||||
'allowed_origins_patterns' => [],
|
||||
|
||||
'allowed_headers' => ['*'],
|
||||
|
||||
'exposed_headers' => [],
|
||||
|
||||
'max_age' => 0,
|
||||
|
||||
'supports_credentials' => true,
|
||||
|
||||
];
|
||||
29
database/factories/Blog/CategoryFactory.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories\Blog;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Category>
|
||||
*/
|
||||
class CategoryFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$name = $this->faker->unique()->word;
|
||||
return [
|
||||
'name' => ucfirst($name),
|
||||
'slug' => Str::slug($name),
|
||||
'description' => $this->faker->paragraph,
|
||||
'short_description' => $this->faker->sentence,
|
||||
'image' => $this->faker->imageUrl(640, 480, 'business', true),
|
||||
];
|
||||
}
|
||||
}
|
||||
41
database/factories/Blog/PostFactory.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories\Blog;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use App\Models\Blog\Post;
|
||||
use App\Models\Blog\Category;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Tag>
|
||||
*/
|
||||
class PostFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
|
||||
protected $model = Post::class;
|
||||
|
||||
|
||||
public function definition(): array
|
||||
{
|
||||
$title = $this->faker->sentence;
|
||||
return [
|
||||
'title' => $title,
|
||||
'body' => $this->faker->paragraphs(5, true),
|
||||
'excerpt' => $this->faker->text(200),
|
||||
'slug' => Str::slug($title) . '-' . $this->faker->unique()->numberBetween(1, 1000),
|
||||
'author_id' => User::inRandomOrder()->first()->id ?? User::factory(),
|
||||
'category_id' => Category::inRandomOrder()->first()->id ?? Category::factory(),
|
||||
'featured_image' => $this->faker->imageUrl(800, 600, 'technics', true),
|
||||
'views' => $this->faker->numberBetween(0, 1000),
|
||||
'likes' => $this->faker->numberBetween(0, 500),
|
||||
'published_at' => $this->faker->dateTimeBetween('-1 years', 'now'),
|
||||
];
|
||||
}
|
||||
}
|
||||
30
database/factories/Blog/TagFactory.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories\Blog;
|
||||
|
||||
use App\Models\Blog\Tag;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Tag>
|
||||
*/
|
||||
class TagFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
|
||||
protected $model = Tag::class;
|
||||
|
||||
public function definition(): array
|
||||
{
|
||||
$name = $this->faker->unique()->word;
|
||||
return [
|
||||
'name' => ucfirst($name),
|
||||
'slug' => Str::slug($name),
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -37,7 +37,7 @@ public function definition(): array
|
||||
*/
|
||||
public function unverified(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
return $this->state(fn(array $attributes) => [
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('skills', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title');
|
||||
$table->string('image'); // URL تصویر
|
||||
$table->text('description'); // توضیحات
|
||||
$table->string('link'); // لینک
|
||||
$table->foreignId('about_me_id')->constrained('about_me')->onDelete('cascade'); // ارتباط با جدول about_me
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('skills');
|
||||
}
|
||||
};
|
||||
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('skills', function (Blueprint $table) {
|
||||
$table->integer('percentage')->after('description'); // اضافه کردن ستون درصد
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('skills', function (Blueprint $table) {
|
||||
$table->dropColumn('percentage');
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->unique();
|
||||
$table->string('slug')->unique();
|
||||
$table->text('description');
|
||||
$table->text('short_description')->nullable();
|
||||
$table->string('image')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('categories');
|
||||
}
|
||||
};
|
||||
@ -11,11 +11,10 @@
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('about_me', function (Blueprint $table) {
|
||||
Schema::create('tags', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title');
|
||||
$table->text('description');
|
||||
$table->string('image'); // URL تصویر
|
||||
$table->string('name')->unique();
|
||||
$table->string('slug')->unique();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
@ -25,6 +24,6 @@ public function up(): void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('about_me');
|
||||
Schema::dropIfExists('tags');
|
||||
}
|
||||
};
|
||||
39
database/migrations/2024_10_13_090833_create_posts_table.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('posts', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title');
|
||||
$table->text('body');
|
||||
$table->text('excerpt'); // توضیحات مختصر
|
||||
$table->string('slug')->unique();
|
||||
$table->unsignedBigInteger('author_id'); // نویسنده
|
||||
$table->foreign('author_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->unsignedBigInteger('category_id'); // دسته بندی
|
||||
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
|
||||
$table->string('featured_image')->nullable(); // تصویر شاخص
|
||||
$table->integer('views')->default(0); // تعداد بازدید
|
||||
$table->integer('likes')->default(0); // تعداد لایک
|
||||
$table->timestamp('published_at')->nullable(); // تاریخ انتشار
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('posts');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('post_tag', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('post_id');
|
||||
$table->unsignedBigInteger('tag_id');
|
||||
$table->timestamps();
|
||||
|
||||
// ایجاد کلیدهای خارجی
|
||||
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
|
||||
$table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
|
||||
|
||||
// جلوگیری از ورود تکراری
|
||||
$table->unique(['post_id', 'tag_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('post_tag');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('related_posts', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('post_id');
|
||||
$table->unsignedBigInteger('related_post_id');
|
||||
$table->timestamps();
|
||||
|
||||
// ایجاد کلیدهای خارجی
|
||||
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
|
||||
$table->foreign('related_post_id')->references('id')->on('posts')->onDelete('cascade');
|
||||
|
||||
// جلوگیری از ورود تکراری
|
||||
$table->unique(['post_id', 'related_post_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('related_posts');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// جدول اصلی about_me
|
||||
Schema::create('website_about_me', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('image'); // URL تصویر
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// جدول ترجمه برای about_me
|
||||
Schema::create('website_about_me_translations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('about_me_id');
|
||||
$table->string('locale')->index(); // زبان (fa, en و غیره)
|
||||
$table->string('title');
|
||||
$table->text('description');
|
||||
$table->timestamps();
|
||||
|
||||
// ارتباط با جدول اصلی
|
||||
$table->foreign('about_me_id')->references('id')->on('website_about_me')->onDelete('cascade');
|
||||
|
||||
// جلوگیری از تکرار یک زبان برای هر about_me
|
||||
$table->unique(['about_me_id', 'locale']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// ابتدا جدول ترجمه باید حذف شود
|
||||
Schema::dropIfExists('website_about_me_translations');
|
||||
// سپس جدول اصلی حذف میشود
|
||||
Schema::dropIfExists('website_about_me');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// جدول اصلی skills
|
||||
Schema::create('website_skills', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('image'); // URL تصویر
|
||||
$table->string('link')->nullable(); // لینک
|
||||
$table->foreignId('about_me_id')->constrained('website_about_me')->onDelete('cascade'); // ارتباط با جدول website_about_me
|
||||
$table->integer('percentage'); // درصد
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// جدول ترجمه برای skills
|
||||
Schema::create('website_skill_translations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('skill_id')->constrained('website_skills')->onDelete('cascade'); // ارتباط با جدول website_skills
|
||||
$table->string('locale')->index(); // مشخص کردن زبان
|
||||
$table->string('title'); // عنوان ترجمهشده
|
||||
$table->text('description'); // توضیحات ترجمهشده
|
||||
$table->unique(['skill_id', 'locale']); // جلوگیری از تکرار ترجمه برای هر زبان
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// ابتدا جدول ترجمه باید حذف شود
|
||||
Schema::dropIfExists('website_skill_translations');
|
||||
// سپس جدول اصلی حذف میشود
|
||||
Schema::dropIfExists('website_skills');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// جدول اصلی services
|
||||
Schema::create('website_services', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('imageSrc'); // URL تصویر
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// جدول ترجمه برای services
|
||||
Schema::create('website_service_translations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('service_id'); // کلید خارجی به جدول اصلی
|
||||
$table->string('locale')->index(); // زبان (fa, en و غیره)
|
||||
$table->string('title'); // عنوان ترجمهشده
|
||||
$table->text('description'); // توضیحات ترجمهشده
|
||||
$table->timestamps();
|
||||
|
||||
// ارتباط با جدول اصلی
|
||||
$table->foreign('service_id')->references('id')->on('website_services')->onDelete('cascade');
|
||||
|
||||
// جلوگیری از تکرار یک زبان برای هر سرویس
|
||||
$table->unique(['service_id', 'locale']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// ابتدا جدول ترجمه باید حذف شود
|
||||
Schema::dropIfExists('website_service_translations');
|
||||
// سپس جدول اصلی حذف میشود
|
||||
Schema::dropIfExists('website_services');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// جدول اصلی testimonials
|
||||
Schema::create('website_testimonials', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('image'); // URL تصویر
|
||||
$table->string('client_link'); // لینک از طرف
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// جدول ترجمه برای testimonials
|
||||
Schema::create('website_testimonial_translations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('testimonial_id'); // کلید خارجی به جدول اصلی
|
||||
$table->string('locale')->index(); // زبان (fa, en و غیره)
|
||||
$table->string('client_name'); // نام ترجمهشده
|
||||
$table->string('client_position'); // سمت ترجمهشده
|
||||
$table->text('feedback'); // نظر ترجمهشده
|
||||
$table->timestamps();
|
||||
|
||||
// ارتباط با جدول اصلی
|
||||
$table->foreign('testimonial_id')->references('id')->on('website_testimonials')->onDelete('cascade');
|
||||
|
||||
// جلوگیری از تکرار یک زبان برای هر testimonial
|
||||
$table->unique(['testimonial_id', 'locale']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// ابتدا جدول ترجمه باید حذف شود
|
||||
Schema::dropIfExists('website_testimonial_translations');
|
||||
// سپس جدول اصلی حذف میشود
|
||||
Schema::dropIfExists('website_testimonials');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// جدول اصلی website_project_categories
|
||||
Schema::create('website_project_categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('image'); // URL تصویر
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// جدول ترجمه برای website_project_categories
|
||||
Schema::create('website_project_category_translations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('category_id'); // کلید خارجی به جدول اصلی
|
||||
$table->string('locale')->index(); // زبان (fa, en و غیره)
|
||||
$table->string('title'); // عنوان ترجمهشده
|
||||
$table->text('description'); // توضیحات ترجمهشده
|
||||
$table->timestamps();
|
||||
|
||||
// ارتباط با جدول اصلی
|
||||
$table->foreign('category_id')->references('id')->on('website_project_categories')->onDelete('cascade');
|
||||
|
||||
// جلوگیری از تکرار یک زبان برای هر دستهبندی
|
||||
$table->unique(['category_id', 'locale']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// ابتدا جدول ترجمه باید حذف شود
|
||||
Schema::dropIfExists('website_project_category_translations');
|
||||
// سپس جدول اصلی حذف میشود
|
||||
Schema::dropIfExists('website_project_categories');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// جدول اصلی website_projects
|
||||
Schema::create('website_projects', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('category_id')->constrained('website_project_categories')->onDelete('cascade'); // کلید خارجی به جدول categories
|
||||
$table->string('image1');
|
||||
$table->string('image2');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// جدول ترجمه برای website_projects
|
||||
Schema::create('website_project_translations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('project_id'); // کلید خارجی به جدول اصلی
|
||||
$table->string('locale')->index(); // زبان (fa, en و غیره)
|
||||
$table->string('title'); // عنوان ترجمهشده
|
||||
$table->text('description'); // توضیحات ترجمهشده
|
||||
$table->timestamps();
|
||||
|
||||
// ارتباط با جدول اصلی
|
||||
$table->foreign('project_id')->references('id')->on('website_projects')->onDelete('cascade');
|
||||
|
||||
// جلوگیری از تکرار یک زبان برای هر پروژه
|
||||
$table->unique(['project_id', 'locale']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// ابتدا جدول ترجمه باید حذف شود
|
||||
Schema::dropIfExists('website_project_translations');
|
||||
// سپس جدول اصلی حذف میشود
|
||||
Schema::dropIfExists('website_projects');
|
||||
}
|
||||
};
|
||||
@ -1,59 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
use App\Models\AboutMe;
|
||||
use App\Models\Skill;
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class AboutMeSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// ایجاد رکورد AboutMe
|
||||
$aboutMe = AboutMe::create([
|
||||
'title' => 'About Me Title',
|
||||
'description' => 'This is a brief description about me.',
|
||||
'image' => '/images/profile.png',
|
||||
]);
|
||||
|
||||
// ایجاد رکوردهای Skill
|
||||
Skill::create([
|
||||
'title' => 'FrontEnd',
|
||||
'image' => '/images/frontend.png',
|
||||
'description' => 'UI design description.',
|
||||
'link' => 'http://example.com/frontend',
|
||||
'percentage' => 90,
|
||||
'about_me_id' => $aboutMe->id,
|
||||
]);
|
||||
|
||||
Skill::create([
|
||||
'title' => 'BackEnd',
|
||||
'image' => '/images/backend.png',
|
||||
'description' => 'BackEnd description.',
|
||||
'link' => 'http://example.com/backend',
|
||||
'percentage' => 80,
|
||||
'about_me_id' => $aboutMe->id,
|
||||
]);
|
||||
Skill::create([
|
||||
'title' => 'UI Design',
|
||||
'image' => '/images/ui.png',
|
||||
'description' => 'UI design description.',
|
||||
'link' => 'http://example.com/ui',
|
||||
'percentage' => 70,
|
||||
'about_me_id' => $aboutMe->id,
|
||||
]);
|
||||
|
||||
Skill::create([
|
||||
'title' => 'UX Design',
|
||||
'image' => '/images/ux.png',
|
||||
'description' => 'UX design description.',
|
||||
'link' => 'http://example.com/ux',
|
||||
'percentage' => 83,
|
||||
'about_me_id' => $aboutMe->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
46
database/seeders/Blog/BlogSeeder.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders\Blog;
|
||||
|
||||
use App\Models\Blog\Category;
|
||||
use App\Models\Blog\Post;
|
||||
use App\Models\Blog\Tag;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class BlogSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
// انتخاب کاربر با id = 1
|
||||
$user = User::find(1);
|
||||
|
||||
if (!$user) {
|
||||
// اگر کاربر با id 1 وجود نداشت، خطا ایجاد کن یا پیام مناسبی بده
|
||||
$this->command->error('User with id 1 not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
// ایجاد دستهبندیها
|
||||
Category::factory(10)->create();
|
||||
|
||||
// ایجاد تگها
|
||||
Tag::factory(20)->create();
|
||||
|
||||
// ایجاد پستها و تخصیص به کاربر با id = 1
|
||||
Post::factory(50)->create([
|
||||
'author_id' => $user->id, // اختصاص پستها به کاربر id 1
|
||||
])->each(function ($post) {
|
||||
// اختصاص تگها به پست
|
||||
$tags = Tag::inRandomOrder()->take(rand(2, 5))->pluck('id');
|
||||
$post->tags()->attach($tags);
|
||||
|
||||
// ایجاد پستهای مرتبط
|
||||
$relatedPosts = Post::inRandomOrder()->where('id', '!=', $post->id)->take(rand(1, 3))->pluck('id');
|
||||
$post->relatedPosts()->attach($relatedPosts);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,11 @@
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\User;
|
||||
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Database\Seeders\Blog\BlogSeeder;
|
||||
use Database\Seeders\Website\AboutMeSeeder;
|
||||
use Database\Seeders\Website\ProjectCategorySeeder;
|
||||
use Database\Seeders\Website\ProjectSeeder;
|
||||
use Database\Seeders\Website\ServiceSeeder;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
@ -16,11 +20,16 @@ public function run(): void
|
||||
// User::factory(10)->create();
|
||||
|
||||
User::factory()->create([
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
'name' => 'parsa aghayi',
|
||||
'email' => 'ceo@parsaaghayi.ir',
|
||||
]);
|
||||
$this->call([
|
||||
AboutMeSeeder::class,
|
||||
// ProjectSeeder::class,
|
||||
ProjectCategorySeeder::class,
|
||||
ProjectSeeder::class,
|
||||
ServiceSeeder::class,
|
||||
BlogSeeder::class
|
||||
// دیگر seeders
|
||||
]);
|
||||
}
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Models\Project;
|
||||
|
||||
class ProjectSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
Project::factory()->count(100)->create();
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Models\Service;
|
||||
|
||||
class ServiceSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$services = [
|
||||
[
|
||||
'title' => 'UI/UX',
|
||||
'description' => 'Lorem ipsum dolor sit amet consectetur. Morbi diam nisi nam diam interdum',
|
||||
'imageSrc' => '/images/ui-ux-vector.svg',
|
||||
'altText' => 'UI/UX Vector',
|
||||
],
|
||||
[
|
||||
'title' => 'Web Design',
|
||||
'description' => 'Lorem ipsum dolor sit amet consectetur. Morbi diam nisi nam diam interdum',
|
||||
'imageSrc' => '/images/web-design-vector.svg',
|
||||
'altText' => 'Web Design Vector',
|
||||
],
|
||||
[
|
||||
'title' => 'App Design',
|
||||
'description' => 'Lorem ipsum dolor sit amet consectetur. Morbi diam nisi nam diam interdum',
|
||||
'imageSrc' => '/images/app-design-vector.svg',
|
||||
'altText' => 'App Design Vector',
|
||||
],
|
||||
[
|
||||
'title' => 'Graphic Design',
|
||||
'description' => 'Lorem ipsum dolor sit amet consectetur. Morbi diam nisi nam diam interdum',
|
||||
'imageSrc' => '/images/graphic-design-vector.svg',
|
||||
'altText' => 'Graphic Design Vector',
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($services as $service) {
|
||||
Service::create($service);
|
||||
}
|
||||
}
|
||||
}
|
||||
151
database/seeders/Website/AboutMeSeeder.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders\Website;
|
||||
|
||||
use App\Models\Website\AboutMe;
|
||||
use App\Models\Website\AboutMeTranslation;
|
||||
use App\Models\Website\Skill;
|
||||
use App\Models\Website\SkillTranslation;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class AboutMeSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// ایجاد رکورد AboutMe بدون ترجمه
|
||||
$aboutMe = AboutMe::create([
|
||||
'image' => '/images/profile.png',
|
||||
]);
|
||||
|
||||
// ایجاد ترجمه انگلیسی
|
||||
AboutMeTranslation::create([
|
||||
'about_me_id' => $aboutMe->id,
|
||||
'locale' => 'en',
|
||||
'title' => 'About Me',
|
||||
'description' => 'I am a web developer with over 10 years of experience in creating dynamic and user-centric web applications. Specializing in React and Next.js, I build scalable solutions that enhance performance and user experience. I enjoy tackling complex challenges, from improving legacy systems to developing new applications. My focus on frontend development and seamless backend integration allows me to deliver innovative results while staying current with industry trends.',
|
||||
]);
|
||||
|
||||
// ایجاد ترجمه فارسی
|
||||
AboutMeTranslation::create([
|
||||
'about_me_id' => $aboutMe->id,
|
||||
'locale' => 'fa',
|
||||
'title' => 'درباره من',
|
||||
'description' => 'من یک توسعهدهنده وب با بیش از 10 سال تجربه در ایجاد برنامههای وب پویا و کاربرمحور هستم. با تخصص در React و Next.js، راهحلهای مقیاسپذیری ایجاد میکنم که عملکرد و تجربه کاربری را بهبود میبخشند. من از حل چالشهای پیچیده لذت میبرم، از بهبود سیستمهای قدیمی گرفته تا توسعه برنامههای جدید. تمرکز من بر توسعه فرانتاند و یکپارچهسازی بیدردسر با بکاند به من این امکان را میدهد که نتایج نوآورانهای ارائه دهم و همزمان با روندهای صنعت بهروز باشم.',
|
||||
]);
|
||||
|
||||
// ایجاد رکوردهای Skill و ترجمههای انگلیسی و فارسی
|
||||
|
||||
// HTML & CSS (SASS, Responsive Design)
|
||||
$htmlSkill = Skill::create([
|
||||
'about_me_id' => $aboutMe->id,
|
||||
'image' => '/images/frontend.png',
|
||||
'percentage' => 95,
|
||||
'link' => 'http://example.com/frontend',
|
||||
]);
|
||||
|
||||
SkillTranslation::create([
|
||||
'skill_id' => $htmlSkill->id,
|
||||
'locale' => 'en',
|
||||
'title' => 'HTML & CSS (SASS, Responsive Design)',
|
||||
'description' => 'Skilled in HTML5, CSS3, including SASS for modular and maintainable stylesheets. Experienced in building responsive web designs.',
|
||||
]);
|
||||
|
||||
SkillTranslation::create([
|
||||
'skill_id' => $htmlSkill->id,
|
||||
'locale' => 'fa',
|
||||
'title' => 'HTML و CSS (SASS، طراحی واکنشگرا)',
|
||||
'description' => 'مهارت در HTML5، CSS3، شامل SASS برای ساخت استایلهای مدولار و قابل نگهداری. تجربه در طراحی وبسایتهای واکنشگرا.',
|
||||
]);
|
||||
|
||||
// React.js and Next.js Development
|
||||
$reactSkill = Skill::create([
|
||||
'about_me_id' => $aboutMe->id,
|
||||
'image' => '/images/backend.png',
|
||||
'percentage' => 90,
|
||||
'link' => 'http://example.com/backend',
|
||||
]);
|
||||
|
||||
SkillTranslation::create([
|
||||
'skill_id' => $reactSkill->id,
|
||||
'locale' => 'en',
|
||||
'title' => 'React.js and Next.js Development',
|
||||
'description' => 'Extensive experience in React.js and Next.js for building scalable and performant web applications.',
|
||||
]);
|
||||
|
||||
SkillTranslation::create([
|
||||
'skill_id' => $reactSkill->id,
|
||||
'locale' => 'fa',
|
||||
'title' => 'توسعه React.js و Next.js',
|
||||
'description' => 'تجربه گسترده در توسعه React.js و Next.js برای ساخت برنامههای وب مقیاسپذیر و پرکاربرد.',
|
||||
]);
|
||||
|
||||
// Backend Development (RESTful APIs, Laravel)
|
||||
$backendSkill = Skill::create([
|
||||
'about_me_id' => $aboutMe->id,
|
||||
'image' => '/images/ui.png',
|
||||
'percentage' => 85,
|
||||
'link' => 'http://example.com/ui',
|
||||
]);
|
||||
|
||||
SkillTranslation::create([
|
||||
'skill_id' => $backendSkill->id,
|
||||
'locale' => 'en',
|
||||
'title' => 'Backend Development (RESTful APIs, Laravel)',
|
||||
'description' => 'Proficient in backend development, building robust RESTful APIs using Laravel and other technologies.',
|
||||
]);
|
||||
|
||||
SkillTranslation::create([
|
||||
'skill_id' => $backendSkill->id,
|
||||
'locale' => 'fa',
|
||||
'title' => 'توسعه بکاند (APIهای RESTful، لاراول)',
|
||||
'description' => 'تسلط به توسعه بکاند و ساخت APIهای RESTful با استفاده از لاراول و دیگر تکنولوژیها.',
|
||||
]);
|
||||
|
||||
// WordPress Development and Customization
|
||||
$wordpressSkill = Skill::create([
|
||||
'about_me_id' => $aboutMe->id,
|
||||
'image' => '/images/ux.png',
|
||||
'percentage' => 90,
|
||||
'link' => 'http://example.com/ux',
|
||||
]);
|
||||
|
||||
SkillTranslation::create([
|
||||
'skill_id' => $wordpressSkill->id,
|
||||
'locale' => 'en',
|
||||
'title' => 'WordPress Development and Customization',
|
||||
'description' => 'Skilled in WordPress development, including theme customization and plugin development.',
|
||||
]);
|
||||
|
||||
SkillTranslation::create([
|
||||
'skill_id' => $wordpressSkill->id,
|
||||
'locale' => 'fa',
|
||||
'title' => 'توسعه و شخصیسازی وردپرس',
|
||||
'description' => 'مهارت در توسعه وردپرس، شامل شخصیسازی قالبها و توسعه افزونهها.',
|
||||
]);
|
||||
|
||||
// Version Control (Git, GitHub)
|
||||
$gitSkill = Skill::create([
|
||||
'about_me_id' => $aboutMe->id,
|
||||
'image' => '/images/ux.png',
|
||||
'percentage' => 80,
|
||||
'link' => 'http://example.com/ux',
|
||||
]);
|
||||
|
||||
SkillTranslation::create([
|
||||
'skill_id' => $gitSkill->id,
|
||||
'locale' => 'en',
|
||||
'title' => 'Version Control (Git, GitHub)',
|
||||
'description' => 'Experienced in version control using Git and GitHub for managing codebases and collaboration.',
|
||||
]);
|
||||
|
||||
SkillTranslation::create([
|
||||
'skill_id' => $gitSkill->id,
|
||||
'locale' => 'fa',
|
||||
'title' => 'کنترل نسخه (Git, GitHub)',
|
||||
'description' => 'تجربه در کنترل نسخه با استفاده از Git و GitHub برای مدیریت کدها و همکاری تیمی.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
41
database/seeders/Website/ProjectCategorySeeder.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders\Website;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Models\Website\ProjectCategory;
|
||||
use App\Models\Website\ProjectCategoryTranslation;
|
||||
|
||||
class ProjectCategorySeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$categories = [
|
||||
['fa' => 'طراحی اپلیکیشن', 'en' => 'App Design'],
|
||||
['fa' => 'فرانت اند', 'en' => 'Front End'],
|
||||
['fa' => 'بک اند', 'en' => 'Backend'],
|
||||
['fa' => 'طراحی وب', 'en' => 'Web Design'],
|
||||
['fa' => 'طراحی گرافیک', 'en' => 'Graphic Design'],
|
||||
];
|
||||
|
||||
foreach ($categories as $key => $category) {
|
||||
// ایجاد دستهبندی اصلی
|
||||
$createdCategory = ProjectCategory::create(['image' => 'category' . ($key + 1) . '.jpg']);
|
||||
|
||||
// ایجاد ترجمهها
|
||||
ProjectCategoryTranslation::create([
|
||||
'category_id' => $createdCategory->id,
|
||||
'locale' => 'fa',
|
||||
'title' => $category['fa'],
|
||||
'description' => 'توضیحات ' . $category['fa'],
|
||||
]);
|
||||
|
||||
ProjectCategoryTranslation::create([
|
||||
'category_id' => $createdCategory->id,
|
||||
'locale' => 'en',
|
||||
'title' => $category['en'],
|
||||
'description' => 'Description for ' . $category['en'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
database/seeders/Website/ProjectSeeder.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders\Website;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Models\Website\Project;
|
||||
use App\Models\Website\ProjectTranslation;
|
||||
use App\Models\Website\ProjectCategory;
|
||||
|
||||
class ProjectSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
// دریافت تمام دستهبندیها
|
||||
$categories = ProjectCategory::all();
|
||||
|
||||
foreach ($categories as $category) {
|
||||
// ایجاد تعداد تصادفی پروژه برای هر دستهبندی
|
||||
$projectCount = rand(5, 10);
|
||||
|
||||
for ($i = 1; $i <= $projectCount; $i++) {
|
||||
// ایجاد پروژه جدید
|
||||
$project = Project::create([
|
||||
'category_id' => $category->id,
|
||||
'image1' => 'project' . $i . '_image1.jpg',
|
||||
'image2' => 'project' . $i . '_image2.jpg'
|
||||
]);
|
||||
|
||||
// ایجاد ترجمهها
|
||||
ProjectTranslation::create([
|
||||
'project_id' => $project->id,
|
||||
'locale' => 'fa',
|
||||
'title' => 'پروژه ' . $i . ' - ' . $category->translations()->where('locale', 'fa')->first()->title,
|
||||
'description' => 'توضیحات پروژه ' . $i . ' برای دستهبندی ' . $category->translations()->where('locale', 'fa')->first()->title,
|
||||
]);
|
||||
|
||||
ProjectTranslation::create([
|
||||
'project_id' => $project->id,
|
||||
'locale' => 'en',
|
||||
'title' => 'Project ' . $i . ' - ' . $category->translations()->where('locale', 'en')->first()->title,
|
||||
'description' => 'Description for project ' . $i . ' in category ' . $category->translations()->where('locale', 'en')->first()->title,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
96
database/seeders/Website/ServiceSeeder.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders\Website;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Models\Website\Service;
|
||||
use App\Models\Website\ServiceTranslation;
|
||||
|
||||
class ServiceSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// خدمات با ترجمههای فارسی
|
||||
$services = [
|
||||
[
|
||||
'imageSrc' => '/images/ui-ux-vector.svg',
|
||||
'translations' => [
|
||||
[
|
||||
'locale' => 'fa',
|
||||
'title' => 'توسعه وب سفارشی',
|
||||
'description' => 'ما برنامههای وب سفارشی را ایجاد میکنیم که نیازهای خاص کسبوکار شما را برآورده میسازد و از آخرین تکنولوژیها برای عملکرد بهینه استفاده میکند.',
|
||||
],
|
||||
[
|
||||
'locale' => 'en',
|
||||
'title' => 'Custom Web Development',
|
||||
'description' => 'We create tailored web applications that meet your unique business requirements, utilizing the latest technologies for optimal performance.',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'imageSrc' => '/images/web-design-vector.svg',
|
||||
'translations' => [
|
||||
[
|
||||
'locale' => 'fa',
|
||||
'title' => 'توسعه فرانتاند',
|
||||
'description' => 'خدمات توسعه فرانتاند ما بر روی ایجاد رابطهای کاربری جذاب و پاسخگو تمرکز دارد که تجربه کاربری را در تمامی دستگاهها بهبود میبخشد.',
|
||||
],
|
||||
[
|
||||
'locale' => 'en',
|
||||
'title' => 'Frontend Development',
|
||||
'description' => 'Our frontend development services focus on crafting engaging, responsive user interfaces that enhance user experience across all devices.',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'imageSrc' => '/images/app-design-vector.svg',
|
||||
'translations' => [
|
||||
[
|
||||
'locale' => 'fa',
|
||||
'title' => 'توسعه بکاند',
|
||||
'description' => 'ما راهحلهای قابل اعتماد توسعه بکاند را ارائه میدهیم و معماریهای سروری و APIهای قوی را برای اطمینان از عملکرد روان و ایمن برنامه ایجاد میکنیم.',
|
||||
],
|
||||
[
|
||||
'locale' => 'en',
|
||||
'title' => 'Backend Development',
|
||||
'description' => 'We provide reliable backend development solutions, building robust server-side architectures and APIs to ensure smooth and secure application functionality.',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'imageSrc' => '/images/graphic-design-vector.svg',
|
||||
'translations' => [
|
||||
[
|
||||
'locale' => 'fa',
|
||||
'title' => 'نگهداری و پشتیبانی وبسایت',
|
||||
'description' => 'خدمات نگهداری و پشتیبانی مداوم ما وبسایت شما را بهروز، امن و با بهترین عملکرد نگه میدارد تا شما بتوانید بر روی کسبوکار اصلی خود تمرکز کنید.',
|
||||
],
|
||||
[
|
||||
'locale' => 'en',
|
||||
'title' => 'Website Maintenance and Support',
|
||||
'description' => 'Our ongoing maintenance and support services keep your website updated, secure, and performing at its best, allowing you to focus on your core business.',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// ذخیره خدمات و ترجمهها
|
||||
foreach ($services as $serviceData) {
|
||||
$service = Service::create([
|
||||
'imageSrc' => $serviceData['imageSrc'],
|
||||
]);
|
||||
|
||||
foreach ($serviceData['translations'] as $translation) {
|
||||
ServiceTranslation::create([
|
||||
'service_id' => $service->id,
|
||||
'locale' => $translation['locale'],
|
||||
'title' => $translation['title'],
|
||||
'description' => $translation['description'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
public/images/parsa2.jpg
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
public/images/parsa21.jpg
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
public/images/parsa22.jpg
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
public/images/projects/project1_image1.jpg
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
public/images/projects/project1_image2.jpg
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
public/images/projects/project2_image1.jpg
Normal file
|
After Width: | Height: | Size: 307 KiB |
BIN
public/images/projects/project2_image2.jpg
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
public/images/projects/project3_image1.jpg
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
public/images/projects/project3_image2.jpg
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
public/images/projects/project4_image1.jpg
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
public/images/projects/project4_image2.jpg
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
public/images/projects/project5_image1.jpg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
public/images/projects/project5_image2.jpg
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
public/images/projects/project6_image1.jpg
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
public/images/projects/project6_image2.jpg
Normal file
|
After Width: | Height: | Size: 110 KiB |
@ -4,7 +4,7 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>Laravel</title>
|
||||
<title>Laravel v1</title>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||
|
||||
@ -2,17 +2,44 @@
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\ProjectController;
|
||||
use App\Http\Controllers\AboutMeController;
|
||||
use App\Http\Controllers\SkillController;
|
||||
use App\Http\Controllers\ServiceController;
|
||||
use App\Http\Controllers\Blog\CategoryController;
|
||||
use App\Http\Controllers\Blog\HomeController;
|
||||
use App\Http\Controllers\Blog\PostController;
|
||||
use App\Http\Controllers\Blog\TagController;
|
||||
// use App\Http\Controllers\SkillController;
|
||||
use App\Http\Controllers\Website\ServiceController;
|
||||
use App\Http\Controllers\Website\AboutMeController;
|
||||
use App\Http\Controllers\Website\ProjectController;
|
||||
|
||||
Route::get('/user', function (Request $request) {
|
||||
return $request->user();
|
||||
})->middleware('auth:sanctum');
|
||||
|
||||
// Route::resource('projects', ProjectController::class);
|
||||
|
||||
Route::resource('projects', ProjectController::class);
|
||||
Route::resource('about-me', AboutMeController::class);
|
||||
Route::resource('skills', SkillController::class);
|
||||
Route::apiResource('services', ServiceController::class);
|
||||
Route::apiResource('services', ServiceController::class);
|
||||
Route::prefix('website')->group(function () {
|
||||
Route::get('about-me/{id}/translation/{locale}', [AboutMeController::class, 'getTranslation']);
|
||||
Route::get('services/{locale}', [ServiceController::class, 'index']); // مسیر جدید برای لیست خدمات با ترجمه
|
||||
Route::get('services/{id}/translation/{locale}', [ServiceController::class, 'showTranslation']);
|
||||
Route::group(['prefix' => 'projects'], function () {
|
||||
Route::get('/translation/{locale}', [ProjectController::class, 'index']);
|
||||
Route::get('/{id}/translation/{locale}', [ProjectController::class, 'show']);
|
||||
Route::post('/', [ProjectController::class, 'store']);
|
||||
Route::put('/{id}', [ProjectController::class, 'update']);
|
||||
Route::delete('/{id}', [ProjectController::class, 'destroy']);
|
||||
});
|
||||
});
|
||||
|
||||
// مسیرهای بلاگ
|
||||
Route::prefix('blog')->group(function () {
|
||||
// پستها
|
||||
Route::apiResource('posts', PostController::class);
|
||||
// دستهبندیها
|
||||
Route::apiResource('categories', CategoryController::class);
|
||||
// تگها
|
||||
Route::apiResource('tags', TagController::class);
|
||||
// مسیر Homepage
|
||||
Route::get('homepage', [HomeController::class, 'index']);
|
||||
Route::get('categories/{slug}/posts', [CategoryController::class, 'getCategoryWithPosts']);
|
||||
});
|
||||
|
||||