This commit is contained in:
2023-11-20 00:32:26 +08:00
parent 9ce3e5c82a
commit 2559d4be1c
37 changed files with 288 additions and 12419 deletions

View File

@@ -4,11 +4,10 @@
use App\Jobs\BrowseAndWriteWithAIJob; use App\Jobs\BrowseAndWriteWithAIJob;
use App\Jobs\PublishIndexPostJob; use App\Jobs\PublishIndexPostJob;
use App\Models\Post;
use Illuminate\Console\Scheduling\Schedule; use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel; use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\Models\Post;
class Kernel extends ConsoleKernel class Kernel extends ConsoleKernel
{ {
/** /**
@@ -22,10 +21,9 @@ protected function schedule(Schedule $schedule): void
})->dailyAt('00:00'); })->dailyAt('00:00');
$schedule->call(function () { $schedule->call(function () {
$future_post = Post::whereNotNull('published_at')->where('status','future')->where('published_at', '>=', now())->orderBy('published_at','ASC')->first(); $future_post = Post::whereNotNull('published_at')->where('status', 'future')->where('published_at', '>=', now())->orderBy('published_at', 'ASC')->first();
PublishIndexPostJob::dispatch($future_post->id)->onQueue('default')->onConnection('default');
PublishIndexPostJob::dispatch($future_post->id)->onQueue('default')->onConnection('default');
})->everyMinute(); })->everyMinute();

View File

@@ -21,9 +21,8 @@ public static function liveAdvanced($se, $se_type, $keyword, $location_name, $la
'language_code' => $language_code, 'language_code' => $language_code,
]; ];
if (!is_empty($search_param)) if (! is_empty($search_param)) {
{ $query['search_param'] = $search_param;
$query['search_param'] = $search_param;
} }
try { try {

View File

@@ -12,55 +12,51 @@
class FrontListController extends Controller class FrontListController extends Controller
{ {
public function search(Request $request)
{
$page_type = 'search';
public function search(Request $request) $query = $request->get('query', '');
{
$page_type = 'search';
$query = $request->get('query', ''); $breadcrumbs = collect([
['name' => 'Home', 'url' => route('front.home')],
['name' => 'Search', 'url' => null],
['name' => $query, 'url' => url()->current()],
]);
$breadcrumbs = collect([ $title = 'Latest News about '.ucwords($query).' in FutureWalker';
['name' => 'Home', 'url' => route('front.home')],
['name' => 'Search', 'url' => null],
['name' => $query, 'url' => url()->current()],
]);
SEOTools::metatags();
SEOTools::twitter();
SEOTools::opengraph();
SEOTools::jsonLd();
SEOTools::setTitle($title, false);
// Use full-text search capabilities of your database
// For example, using MySQL's full-text search with MATCH...AGAINST
$posts = Post::with('category')
->where('status', 'publish')
->whereRaw("to_tsvector('english', title || ' ' || bites) @@ to_tsquery('english', ?)", [$query])
->orderBy('published_at', 'desc')
->cursorPaginate(10);
$title = 'Latest News about ' . ucwords($query) . ' in FutureWalker'; // breadcrumb json ld
$listItems = [];
SEOTools::metatags(); foreach ($breadcrumbs as $index => $breadcrumb) {
SEOTools::twitter(); $listItems[] = [
SEOTools::opengraph(); 'name' => $breadcrumb['name'],
SEOTools::jsonLd(); 'url' => $breadcrumb['url'],
SEOTools::setTitle($title, false); ];
}
// Use full-text search capabilities of your database $breadcrumb_context = Context::create('breadcrumb_list', [
// For example, using MySQL's full-text search with MATCH...AGAINST 'itemListElement' => $listItems,
$posts = Post::with('category') ]);
->where('status', 'publish')
->whereRaw("to_tsvector('english', title || ' ' || bites) @@ to_tsquery('english', ?)", [$query])
->orderBy('published_at', 'desc')
->cursorPaginate(10);
// breadcrumb json ld return view('front.post_list', compact('posts', 'breadcrumbs', 'breadcrumb_context', 'title', 'page_type'));
$listItems = [];
foreach ($breadcrumbs as $index => $breadcrumb) {
$listItems[] = [
'name' => $breadcrumb['name'],
'url' => $breadcrumb['url'],
];
} }
$breadcrumb_context = Context::create('breadcrumb_list', [
'itemListElement' => $listItems,
]);
return view('front.post_list', compact('posts', 'breadcrumbs', 'breadcrumb_context', 'title','page_type'));
}
public function index(Request $request) public function index(Request $request)
{ {
$page_type = 'default'; $page_type = 'default';
@@ -96,7 +92,7 @@ public function index(Request $request)
'itemListElement' => $listItems, 'itemListElement' => $listItems,
]); ]);
return view('front.post_list', compact('posts', 'breadcrumbs', 'breadcrumb_context','page_type')); return view('front.post_list', compact('posts', 'breadcrumbs', 'breadcrumb_context', 'page_type'));
} }
public function category(Request $request, $category_slug) public function category(Request $request, $category_slug)
@@ -147,6 +143,6 @@ public function category(Request $request, $category_slug)
'itemListElement' => $listItems, 'itemListElement' => $listItems,
]); ]);
return view('front.post_list', compact('category', 'posts', 'breadcrumbs', 'breadcrumb_context','page_type')); return view('front.post_list', compact('category', 'posts', 'breadcrumbs', 'breadcrumb_context', 'page_type'));
} }
} }

View File

@@ -3,7 +3,6 @@
namespace App\Jobs; namespace App\Jobs;
use App\Jobs\Tasks\PublishIndexPostTask; use App\Jobs\Tasks\PublishIndexPostTask;
use App\Models\Post;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;

View File

@@ -5,11 +5,11 @@
use App\Helpers\FirstParty\OpenAI\OpenAI; use App\Helpers\FirstParty\OpenAI\OpenAI;
use App\Helpers\FirstParty\OSSUploader\OSSUploader; use App\Helpers\FirstParty\OSSUploader\OSSUploader;
use App\Jobs\SchedulePublishPost; use App\Jobs\SchedulePublishPost;
use App\Models\Entity;
use App\Models\PostEntity;
use App\Models\Category; use App\Models\Category;
use App\Models\Entity;
use App\Models\Post; use App\Models\Post;
use App\Models\PostCategory; use App\Models\PostCategory;
use App\Models\PostEntity;
use App\Models\SerpUrlResearch; use App\Models\SerpUrlResearch;
use App\Models\ServiceCostUsage; use App\Models\ServiceCostUsage;
use Exception; use Exception;
@@ -78,100 +78,84 @@ public static function handle(int $post_id)
$post = self::setPostImage($post); $post = self::setPostImage($post);
} }
if (isset($post_meta_response->output->society_impact)) if (isset($post_meta_response->output->society_impact)) {
{ if (! is_empty($post_meta_response->output->society_impact)) {
if (!is_empty($post_meta_response->output->society_impact)) $post->society_impact = $post_meta_response->output->society_impact;
{ }
$post->society_impact = $post_meta_response->output->society_impact;
}
} }
if (isset($post_meta_response->output->society_impact_level)) if (isset($post_meta_response->output->society_impact_level)) {
{ if (! is_empty($post_meta_response->output->society_impact_level)) {
if (!is_empty($post_meta_response->output->society_impact_level)) $post->society_impact = $post_meta_response->output->society_impact_level;
{ }
$post->society_impact = $post_meta_response->output->society_impact_level;
}
} }
if ($post->save()) { if ($post->save()) {
// Set Category // Set Category
$category_name = 'Updates'; $category_name = 'Updates';
if ((isset($post_meta_response->output->category)) && (!is_empty($post_meta_response->output->category))) if ((isset($post_meta_response->output->category)) && (! is_empty($post_meta_response->output->category))) {
{ $category_name = $post_meta_response?->output?->category;
$category_name = $post_meta_response?->output?->category;
}
$category = Category::where('name', $category_name)->first();
if (is_null($category))
{
$category = Category::where('name', 'Updates')->first();
}
// Set Post Category
$post_category = PostCategory::where('post_id', $post->id)->first();
if (is_null($post_category))
{
$post_category = new PostCategory;
$post_category->post_id = $post->id;
}
$post_category->category_id = $category->id;
$post_category->save();
// Set Post Entities
if (isset($post_meta_response->output->entities))
{
$entity_names = [];
if (is_array($post_meta_response->output->entities))
{
$entity_names = $post_meta_response->output->entities;
} }
if (count($entity_names) > 0) $category = Category::where('name', $category_name)->first();
{
$previous_post_entities = PostEntity::where('post_id', $post->id)->delete();
foreach ($entity_names as $entity_name) if (is_null($category)) {
{ $category = Category::where('name', 'Updates')->first();
$entity_name = trim($entity_name);
$entity = Entity::where('name', $entity_name)->first();
if (is_null($entity))
{
$entity = new Entity;
$entity->name = $entity_name;
$entity->slug = str_slug($entity_name);
$entity->save();
}
$post_entity = PostEntity::where('post_id', $post->id)
->where('entity_id', $entity->id)
->first();
if (is_null($post_entity))
{
$post_entity = new PostEntity;
$post_entity->post_id = $post->id;
$post_entity->entity_id = $entity->id;
$post_entity->save();
}
}
} }
}
// Set Schedule Publish // Set Post Category
SchedulePublishPost::dispatch($post->id, 'future')->onQueue('default')->onConnection('default'); $post_category = PostCategory::where('post_id', $post->id)->first();
if (is_null($post_category)) {
$post_category = new PostCategory;
$post_category->post_id = $post->id;
}
$post_category->category_id = $category->id;
$post_category->save();
// Set Post Entities
if (isset($post_meta_response->output->entities)) {
$entity_names = [];
if (is_array($post_meta_response->output->entities)) {
$entity_names = $post_meta_response->output->entities;
}
if (count($entity_names) > 0) {
$previous_post_entities = PostEntity::where('post_id', $post->id)->delete();
foreach ($entity_names as $entity_name) {
$entity_name = trim($entity_name);
$entity = Entity::where('name', $entity_name)->first();
if (is_null($entity)) {
$entity = new Entity;
$entity->name = $entity_name;
$entity->slug = str_slug($entity_name);
$entity->save();
}
$post_entity = PostEntity::where('post_id', $post->id)
->where('entity_id', $entity->id)
->first();
if (is_null($post_entity)) {
$post_entity = new PostEntity;
$post_entity->post_id = $post->id;
$post_entity->entity_id = $entity->id;
$post_entity->save();
}
}
}
}
// Set Schedule Publish
SchedulePublishPost::dispatch($post->id, 'future')->onQueue('default')->onConnection('default');
} }
} }

View File

@@ -13,9 +13,8 @@ public static function handle(int $post_id)
{ {
$post = Post::find($post_id); $post = Post::find($post_id);
if (is_null($post)) if (is_null($post)) {
{ return;
return ;
} }
$post->status = 'publish'; $post->status = 'publish';

View File

@@ -12,28 +12,25 @@
/** /**
* Class Entity * Class Entity
* *
* @property int $id * @property int $id
* @property string $name * @property string $name
* @property Carbon|null $created_at * @property Carbon|null $created_at
* @property Carbon|null $updated_at * @property Carbon|null $updated_at
*
* @property Collection|PostEntity[] $post_entities * @property Collection|PostEntity[] $post_entities
*
* @package App\Models
*/ */
class Entity extends Model class Entity extends Model
{ {
protected $table = 'entities'; protected $table = 'entities';
protected $fillable = [ protected $fillable = [
'name', 'name',
'slug', 'slug',
'description' 'description',
]; ];
public function post_entities() public function post_entities()
{ {
return $this->hasMany(PostEntity::class); return $this->hasMany(PostEntity::class);
} }
} }

View File

@@ -11,39 +11,36 @@
/** /**
* Class PostEntity * Class PostEntity
* *
* @property int $id * @property int $id
* @property int $post_id * @property int $post_id
* @property int $entity_id * @property int $entity_id
* @property Carbon|null $created_at * @property Carbon|null $created_at
* @property Carbon|null $updated_at * @property Carbon|null $updated_at
*
* @property Post $post * @property Post $post
* @property Entity $entity * @property Entity $entity
*
* @package App\Models
*/ */
class PostEntity extends Model class PostEntity extends Model
{ {
protected $table = 'post_entities'; protected $table = 'post_entities';
protected $casts = [ protected $casts = [
'post_id' => 'int', 'post_id' => 'int',
'entity_id' => 'int' 'entity_id' => 'int',
]; ];
protected $fillable = [ protected $fillable = [
'post_id', 'post_id',
'entity_id' 'entity_id',
]; ];
public function post() public function post()
{ {
return $this->belongsTo(Post::class); return $this->belongsTo(Post::class);
} }
public function entity() public function entity()
{ {
return $this->belongsTo(Entity::class); return $this->belongsTo(Entity::class);
} }
} }

View File

@@ -20,7 +20,7 @@ public function up(): void
$table->json('keywords')->nullable(); $table->json('keywords')->nullable();
$table->mediumText('bites')->nullable(); $table->mediumText('bites')->nullable();
$table->mediumText('society_impact')->nullable(); $table->mediumText('society_impact')->nullable();
$table->enum('society_impact_level', ['low','medium','high'])->default('low'); $table->enum('society_impact_level', ['low', 'medium', 'high'])->default('low');
$table->foreignId('author_id')->nullable(); $table->foreignId('author_id')->nullable();
$table->mediumText('featured_image')->nullable(); $table->mediumText('featured_image')->nullable();
$table->text('body')->nullable(); $table->text('body')->nullable();

View File

@@ -3,7 +3,7 @@
# eval 'php artisan optimize:clear'; # eval 'php artisan optimize:clear';
# eval 'php artisan responsecache:clear'; # eval 'php artisan responsecache:clear';
# eval 'php artisan opcache:clear'; # eval 'php artisan opcache:clear';
eval 'APP_URL=https://FutureWalker.com php artisan ziggy:generate'; eval 'APP_URL=https://futurewalker.co php artisan ziggy:generate';
eval 'blade-formatter --write resources/**/*.blade.php'; eval 'blade-formatter --write resources/**/*.blade.php';
eval './vendor/bin/pint'; eval './vendor/bin/pint';
eval 'npm run build'; eval 'npm run build';

View File

@@ -1 +1 @@
import{_ as i}from"./vue-7b541fc9.js";const n={name:"LqipLoader",mounted(){this.initLqipLoading()},methods:{initLqipLoading(){const e=document.getElementsByTagName("img");for(let t=0;t<e.length;t++)e[t].getAttribute("data-src")&&(e[t].onload=function(){this.classList.remove("lqip-blur")},e[t].setAttribute("src",e[t].getAttribute("data-src")))}}};function o(e,t,r,s,a,c){return null}const m=i(n,[["render",o]]);export{m as default}; import{_ as i}from"./vue-119a3b87.js";const n={name:"LqipLoader",mounted(){this.initLqipLoading()},methods:{initLqipLoading(){const e=document.getElementsByTagName("img");for(let t=0;t<e.length;t++)e[t].getAttribute("data-src")&&(e[t].onload=function(){this.classList.remove("lqip-blur")},e[t].setAttribute("src",e[t].getAttribute("data-src")))}}};function o(e,t,r,s,a,c){return null}const m=i(n,[["render",o]]);export{m as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1 +1 @@
import{_ as o,o as p,c,a as r,b as u,p as i,d as m,e as g,f as _,g as d,v as f,Z as n,h as l}from"./vue-7b541fc9.js";const A={name:"AppAuth"};function $(s,a,t,Z,w,x){return p(),c("div")}const h=o(A,[["render",$]]),e=r({AppAuth:h}),v=Object.assign({});e.use(u());e.use(i,m);e.use(g);e.use(_);e.use(d);e.use(f.ZiggyVue,n);window.Ziggy=n;Object.entries({...v}).forEach(([s,a])=>{const t=s.split("/").pop().replace(/\.\w+$/,"").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();e.component(t,l(a))});e.mount("#app"); import{_ as o,o as p,c,a as r,b as u,p as i,d as m,e as g,f as _,g as d,v as f,Z as n,h as l}from"./vue-119a3b87.js";const A={name:"AppAuth"};function $(s,a,t,Z,w,x){return p(),c("div")}const h=o(A,[["render",$]]),e=r({AppAuth:h}),v=Object.assign({});e.use(u());e.use(i,m);e.use(g);e.use(_);e.use(d);e.use(f.ZiggyVue,n);window.Ziggy=n;Object.entries({...v}).forEach(([s,a])=>{const t=s.split("/").pop().replace(/\.\w+$/,"").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();e.component(t,l(a))});e.mount("#app");

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,9 @@
{ {
"_vue-7b541fc9.js": { "_vue-119a3b87.js": {
"css": [ "css": [
"assets/vue-935fc652.css" "assets/vue-935fc652.css"
], ],
"file": "assets/vue-7b541fc9.js" "file": "assets/vue-119a3b87.js"
}, },
"node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff": { "node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff": {
"file": "assets/bootstrap-icons-4d4572ef.woff", "file": "assets/bootstrap-icons-4d4572ef.woff",
@@ -50,9 +50,9 @@
"src": "resources/fonts/Inter/Inter-Thin.ttf" "src": "resources/fonts/Inter/Inter-Thin.ttf"
}, },
"resources/js/app-auth.js": { "resources/js/app-auth.js": {
"file": "assets/app-auth-863829a4.js", "file": "assets/app-auth-cd6b6188.js",
"imports": [ "imports": [
"_vue-7b541fc9.js" "_vue-119a3b87.js"
], ],
"isEntry": true, "isEntry": true,
"src": "resources/js/app-auth.js" "src": "resources/js/app-auth.js"
@@ -61,28 +61,28 @@
"dynamicImports": [ "dynamicImports": [
"resources/js/vue/front/LqipLoader.vue" "resources/js/vue/front/LqipLoader.vue"
], ],
"file": "assets/app-front-da28b0cc.js", "file": "assets/app-front-7da267b6.js",
"imports": [ "imports": [
"_vue-7b541fc9.js" "_vue-119a3b87.js"
], ],
"isEntry": true, "isEntry": true,
"src": "resources/js/app-front.js" "src": "resources/js/app-front.js"
}, },
"resources/js/vue/front/LqipLoader.vue": { "resources/js/vue/front/LqipLoader.vue": {
"file": "assets/LqipLoader-343b1ab3.js", "file": "assets/LqipLoader-63b84826.js",
"imports": [ "imports": [
"_vue-7b541fc9.js" "_vue-119a3b87.js"
], ],
"isDynamicEntry": true, "isDynamicEntry": true,
"src": "resources/js/vue/front/LqipLoader.vue" "src": "resources/js/vue/front/LqipLoader.vue"
}, },
"resources/sass/app-auth.scss": { "resources/sass/app-auth.scss": {
"file": "assets/app-auth-32da185d.css", "file": "assets/app-auth-38851d9d.css",
"isEntry": true, "isEntry": true,
"src": "resources/sass/app-auth.scss" "src": "resources/sass/app-auth.scss"
}, },
"resources/sass/app-front.scss": { "resources/sass/app-front.scss": {
"file": "assets/app-front-ecc2f041.css", "file": "assets/app-front-1cc890bf.css",
"isEntry": true, "isEntry": true,
"src": "resources/sass/app-front.scss" "src": "resources/sass/app-front.scss"
}, },

Binary file not shown.

View File

@@ -1,64 +1,7 @@
const Ziggy = { const Ziggy = {"url":"https:\/\/futurewalker.co","port":null,"defaults":{},"routes":{"debugbar.openhandler":{"uri":"_debugbar\/open","methods":["GET","HEAD"]},"debugbar.clockwork":{"uri":"_debugbar\/clockwork\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"debugbar.assets.css":{"uri":"_debugbar\/assets\/stylesheets","methods":["GET","HEAD"]},"debugbar.assets.js":{"uri":"_debugbar\/assets\/javascript","methods":["GET","HEAD"]},"debugbar.cache.delete":{"uri":"_debugbar\/cache\/{key}\/{tags?}","methods":["DELETE"],"parameters":["key","tags"]},"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"laravelpwa.manifest":{"uri":"manifest.json","methods":["GET","HEAD"]},"laravelpwa.":{"uri":"offline","methods":["GET","HEAD"]},"ignition.healthCheck":{"uri":"_ignition\/health-check","methods":["GET","HEAD"]},"ignition.executeSolution":{"uri":"_ignition\/execute-solution","methods":["POST"]},"ignition.updateConfig":{"uri":"_ignition\/update-config","methods":["POST"]},"feeds.main":{"uri":"feeds\/posts-feed","methods":["GET","HEAD"]},"front.home":{"uri":"\/","methods":["GET","HEAD"]},"front.terms":{"uri":"terms","methods":["GET","HEAD"]},"front.privacy":{"uri":"privacy","methods":["GET","HEAD"]},"front.disclaimer":{"uri":"disclaimer","methods":["GET","HEAD"]},"front.all":{"uri":"latest","methods":["GET","HEAD"]},"front.search":{"uri":"search","methods":["POST"]},"front.post":{"uri":"{category_slug}\/{slug}","methods":["GET","HEAD"],"parameters":["category_slug","slug"]},"front.category":{"uri":"{category_slug}","methods":["GET","HEAD"],"wheres":{"category_slug":"^(updates|opinions|features|new-launches|tutorials|reviews)$"},"parameters":["category_slug"]}}};
url: "https://FutureWalker.com",
port: null,
defaults: {},
routes: {
"debugbar.openhandler": { uri: "_debugbar/open", methods: ["GET", "HEAD"] },
"debugbar.clockwork": {
uri: "_debugbar/clockwork/{id}",
methods: ["GET", "HEAD"],
},
"debugbar.assets.css": {
uri: "_debugbar/assets/stylesheets",
methods: ["GET", "HEAD"],
},
"debugbar.assets.js": {
uri: "_debugbar/assets/javascript",
methods: ["GET", "HEAD"],
},
"debugbar.cache.delete": {
uri: "_debugbar/cache/{key}/{tags?}",
methods: ["DELETE"],
},
"sanctum.csrf-cookie": {
uri: "sanctum/csrf-cookie",
methods: ["GET", "HEAD"],
},
"laravelpwa.manifest": { uri: "manifest.json", methods: ["GET", "HEAD"] },
"laravelpwa.": { uri: "offline", methods: ["GET", "HEAD"] },
"ignition.healthCheck": {
uri: "_ignition/health-check",
methods: ["GET", "HEAD"],
},
"ignition.executeSolution": {
uri: "_ignition/execute-solution",
methods: ["POST"],
},
"ignition.updateConfig": {
uri: "_ignition/update-config",
methods: ["POST"],
},
"feeds.main": { uri: "feeds/posts-feed", methods: ["GET", "HEAD"] },
"front.home": { uri: "/", methods: ["GET", "HEAD"] },
"front.terms": { uri: "terms", methods: ["GET", "HEAD"] },
"front.privacy": { uri: "privacy", methods: ["GET", "HEAD"] },
"front.disclaimer": { uri: "disclaimer", methods: ["GET", "HEAD"] },
"front.all": { uri: "news", methods: ["GET", "HEAD"] },
"front.post.redirect": { uri: "news/{slug}", methods: ["GET", "HEAD"] },
"front.post": { uri: "{category_slug}/{slug}", methods: ["GET", "HEAD"] },
"front.category": {
uri: "{category_slug}",
methods: ["GET", "HEAD"],
wheres: {
category_slug:
"^(automotive|business|trading|information-technology|marketing|office|telecommunications|food-drink|collectibles|pets|photography|hobbies-gifts|hunting-fishing|law|politics|home-garden|shopping|fashion-clothing|real-estate|family|wedding|immigration|society|education|languages|health|beauty|psychology|wellness|religion-spirituality|tips-tricks|how-to|holiday|world-festivals|travel|outdoors|computer|phones|gadgets|technology|social-networks|ai)$",
},
},
},
};
if (typeof window !== "undefined" && typeof window.Ziggy !== "undefined") { if (typeof window !== 'undefined' && typeof window.Ziggy !== 'undefined') {
Object.assign(Ziggy.routes, window.Ziggy.routes); Object.assign(Ziggy.routes, window.Ziggy.routes);
} }
export { Ziggy }; export { Ziggy };

View File

@@ -1,6 +1,9 @@
<aside class="p-4 mb-3 bg-black text-white rounded-3 shadow-sm"> <aside class="p-4 mb-3 bg-black text-white rounded-3 shadow-sm">
<h4 class="font-family-roboto-condensed">About <span class="text-uppercase">FutureWalker</span></h4> <h4 class="font-family-roboto-condensed">About <span class="text-uppercase">FutureWalker</span></h4>
<p class="mb-0"> <p class="mb-0">
FutureWalker is an innovative news platform specializing in cutting-edge technology and AI developments. We provide insightful coverage on the latest breakthroughs and trends, offering our audience a front-row seat to the advancements shaping our future. Stay informed and ahead with FutureWalker, your go-to source for tech news that matters. FutureWalker is an innovative news platform specializing in cutting-edge technology and AI developments. We
provide insightful coverage on the latest breakthroughs and trends, offering our audience a front-row seat to
the advancements shaping our future. Stay informed and ahead with FutureWalker, your go-to source for tech news
that matters.
</p> </p>
</aside> </aside>

View File

@@ -1,8 +1,7 @@
<div class="row g-3 border-0 overflow-hidden flex-md-row mb-4 h-md-250 position-relative bg-white"> <div class="row g-3 border-0 overflow-hidden flex-md-row mb-4 h-md-250 position-relative bg-white">
<div class="col-12 col-lg-3 d-flex" style="height:100%;"> <div class="col-12 col-lg-3 d-flex" style="height:100%;">
<div class="align-self-center"> <div class="align-self-center">
<img class="img-fluid rounded-4 shadow" src="{{ $post->featured_image }}" <img class="img-fluid rounded-4 shadow" src="{{ $post->featured_image }}" alt="{{ $post->title }}">
alt="{{ $post->title }}">
</div> </div>
</div> </div>

View File

@@ -1,9 +1,10 @@
<aside> <aside>
<form class="d-flex mb-3" action="{{ route('front.search')}}" method="POST"> <form class="d-flex mb-3" action="{{ route('front.search') }}" method="POST">
@csrf @csrf
<input name="query" class="form-control me-2" type="search" placeholder="Search for AI news..." aria-label="Search"> <input name="query" class="form-control me-2" type="search" placeholder="Search for AI news..."
<button class="btn btn-outline-primary" type="submit"> aria-label="Search">
<i class="bi bi-search"></i> <button class="btn btn-outline-primary" type="submit">
</button> <i class="bi bi-search"></i>
</form> </button>
</aside> </form>
</aside>

View File

@@ -1,7 +1,7 @@
@include('front.partials.about') @include('front.partials.about')
@include('front.partials.search') @include('front.partials.search')
{{-- {{--
<aside class="text-center"> <aside class="text-center">
<h3 class="font-family-roboto-condensed h4 text-uppercase">Never miss a news</h3> <h3 class="font-family-roboto-condensed h4 text-uppercase">Never miss a news</h3>
<div class="d-flex flex-row justify-content-center"> <div class="d-flex flex-row justify-content-center">
@@ -11,7 +11,7 @@
{{-- <a href="https://twitter.com/futurewalker" target="_blank" class="mx-1 btn btn-link mb-2"> {{-- <a href="https://twitter.com/futurewalker" target="_blank" class="mx-1 btn btn-link mb-2">
<i class="bi bi-twitter"></i> <i class="bi bi-twitter"></i>
</a> --}} </a> --}}
{{-- <a href="https://www.youtube.com/user/hackaday" target="_blank" class="mx-1 btn btn-link mb-2"> {{-- <a href="https://www.youtube.com/user/hackaday" target="_blank" class="mx-1 btn btn-link mb-2">
<i class="bi bi-youtube"></i> <i class="bi bi-youtube"></i>
</a> </a>
<a href="https://hackaday.com/blog/feed/" target="_blank" class="mx-1 btn btn-link mb-2"> <a href="https://hackaday.com/blog/feed/" target="_blank" class="mx-1 btn btn-link mb-2">
@@ -19,4 +19,4 @@
</a> </a>
</div> </div>
</aside> </aside>
--}} --}}

View File

@@ -8,16 +8,16 @@
<div class="col-md-8"> <div class="col-md-8">
<h1 class="pb-2 h2 font-family-roboto-condensed"> <h1 class="pb-2 h2 font-family-roboto-condensed">
@if($page_type == 'search') @if ($page_type == 'search')
@if(isset($title)) @if (isset($title))
{{ $title }} {{ $title }}
@endif @endif
@else @else
@if (isset($category) && !is_null($category)) @if (isset($category) && !is_null($category))
{{ $category->name }} News from FutureWalker {{ $category->name }} News from FutureWalker
@else @else
AI &amp; Tech News from FutureWalker AI &amp; Tech News from FutureWalker
@endif @endif
@endif @endif
</h1> </h1>
@if ($posts->count() > 0) @if ($posts->count() > 0)
@@ -38,9 +38,9 @@
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="position-sticky" style="top: 2rem;"> <div class="position-sticky" style="top: 2rem;">
@include('front.partials.sidebar') @include('front.partials.sidebar')
</div> </div>
</div> </div>
</div> </div>
</main> </main>

View File

@@ -18,94 +18,98 @@
</div> </div>
@if ($featured_posts->count() > 0) @if ($featured_posts->count() > 0)
<div class="container-lg py-4"> <div class="container-lg py-4">
<div class="text-center"> <div class="text-center">
<h2 id="latest-news" class="fw-bold font-family-roboto-condensed mb-3 h2">Featured News</h2> <h2 id="latest-news" class="fw-bold font-family-roboto-condensed mb-3 h2">Featured News</h2>
</div> </div>
<div class="row g-3"> <div class="row g-3">
@foreach ($featured_posts as $post) @foreach ($featured_posts as $post)
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<div class="card border-0" style="height:100%;"> <div class="card border-0" style="height:100%;">
<div class="ratio ratio-16x9"> <div class="ratio ratio-16x9">
<img src="{{ $post->featured_image }}" alt="" class="rounded-4 card-img-top shadow" <img src="{{ $post->featured_image }}" alt=""
style="object-fit: cover;"> class="rounded-4 card-img-top shadow" style="object-fit: cover;">
</div> </div>
<div class="card-body px-0"> <div class="card-body px-0">
<h3 class="h4 fw-bold font-family-roboto-condensed"> <h3 class="h4 fw-bold font-family-roboto-condensed">
<a href="{{ route('front.post', ['category_slug' => $post->category->slug,'slug' => $post->slug]) }}">{{ $post->title }}</a> <a
</h3> href="{{ route('front.post', ['category_slug' => $post->category->slug, 'slug' => $post->slug]) }}">{{ $post->title }}</a>
<p>{{ str_first_sentence($post->bites) }}</p> </h3>
<p>{{ str_first_sentence($post->bites) }}</p>
</div>
</div> </div>
</div> </div>
@endforeach
</div> </div>
@endforeach
</div> </div>
</div>
@endif @endif
@if ($latest_posts->count() > 0) @if ($latest_posts->count() > 0)
<div class="container-lg py-4"> <div class="container-lg py-4">
<div class="row"> <div class="row">
<div class="col-12 col-lg-8 mb-3"> <div class="col-12 col-lg-8 mb-3">
<div class="text-start"> <div class="text-start">
<h2 id="latest-news" class="fw-bold font-family-roboto-condensed mb-3 h2">Latest News</h2> <h2 id="latest-news" class="fw-bold font-family-roboto-condensed mb-3 h2">Latest News</h2>
</div> </div>
<div class="row g-3 mb-4"> <div class="row g-3 mb-4">
@foreach ($latest_posts as $post) @foreach ($latest_posts as $post)
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<div class="card bg-white border-0 shadow" style="height:100%;"> <div class="card bg-white border-0 shadow" style="height:100%;">
<div class="card-body d-flex"> <div class="card-body d-flex">
<div class="row align-self-center"> <div class="row align-self-center">
<div class="col-12 col-lg-5 d-flex py-1" style="height:100%;"> <div class="col-12 col-lg-5 d-flex py-1" style="height:100%;">
<div class="align-self-center"> <div class="align-self-center">
<img class="img-fluid rounded-4" src="{{ $post->featured_image }}" <img class="img-fluid rounded-4" src="{{ $post->featured_image }}"
alt="{{ $post->title }}"> alt="{{ $post->title }}">
</div> </div>
</div> </div>
<div class="col-12 col-lg-7 d-flex py-1" style="height:100%;"> <div class="col-12 col-lg-7 d-flex py-1" style="height:100%;">
<div class="align-self-center"> <div class="align-self-center">
<div class=""> <div class="">
<h3 class="h6 mb-0 fw-bold font-family-roboto-condensed"> <h3 class="h6 mb-0 fw-bold font-family-roboto-condensed">
<a href="{{ route('front.post', ['category_slug' => $post->category->slug,'slug' => $post->slug]) }}" class="fw-bold" <a href="{{ route('front.post', ['category_slug' => $post->category->slug, 'slug' => $post->slug]) }}"
style=" display: -webkit-box; class="fw-bold"
style=" display: -webkit-box;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden;">{{ $post->title }}</a></h3> overflow: hidden;">{{ $post->title }}</a>
</div> </h3>
<div><small </div>
class="text-secondary">{{ $post->published_at->diffForHumans() }}</small> <div><small
class="text-secondary">{{ $post->published_at->diffForHumans() }}</small>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> @endforeach
</div>
<div class="w-full text-center">
<a href="{{ route('front.all') }}"
class="btn btn-outline-primary px-4 rounded-pill text-decoration-none">Discover More
News</a>
</div> </div>
</div> </div>
@endforeach <div class="col-12 col-lg-4 mb-3">
</div> <div class="position-sticky" style="top: 2rem;">
<div class="w-full text-center"> @include('front.partials.sidebar')
<a href="{{ route('front.all') }}"
class="btn btn-outline-primary px-4 rounded-pill text-decoration-none">Discover More News</a>
</div>
</div>
<div class="col-12 col-lg-4 mb-3">
<div class="position-sticky" style="top: 2rem;">
@include('front.partials.sidebar')
</div>
</div>
</div> </div>
</div>
</div> </div>
</div>
@endif @endif

View File

@@ -6,7 +6,6 @@
use App\Jobs\FillPostMetadataJob; use App\Jobs\FillPostMetadataJob;
use App\Jobs\GenerateArticleFeaturedImageJob; use App\Jobs\GenerateArticleFeaturedImageJob;
use App\Jobs\GenerateArticleJob; use App\Jobs\GenerateArticleJob;
use App\Jobs\SchedulePublishPost;
use App\Jobs\Tasks\GetNewsSerpTask; use App\Jobs\Tasks\GetNewsSerpTask;
use App\Jobs\Tasks\ParseNewsSerpDomainsTask; use App\Jobs\Tasks\ParseNewsSerpDomainsTask;
use App\Jobs\Tasks\ScrapeUrlBodyTask; use App\Jobs\Tasks\ScrapeUrlBodyTask;