building a website with laravel,react js and inertia js

 laravel installer

larvel valet or laragon => torun locally

laravel run blog

open a project in ide code .

lets link our db ot .env

app_url

valet link linked_in blog


post resource


art make model post -a --api


post model

post factory

posts migration

post seeder

store post request

update post request

post controller

postpolicy

api.ph


route::apiRsource('posts',postcontroller:class);

php artisan routes:list

php artisan migrate


post::factory()->count(10)->create();

in seeder

php artisan db:seed --class=PostSeeder


$hidden sensitive attributes

php artisan maek:resurce postresiurces


resource folder

it will writen everything 


react setup 


repository with react (frontend and backend seperate)

reposirou with laravel api

its possble with laravle mxi

vite with we can isntall 

npm create vite@latest frontend --template react




in frontend 

npm install -D tailwindcss postcss autoprefixer


npx tailwindcss init -p

it will generate tailwind.config.js

path all of your javascript contain tailw 

in congent

this is telling tail wind the paths to all of yur javascript component  that will contain tailw wind  class names

modify like belo 

https://github.com/LinkedInLearning/building-a-website-with-laravel-php-and-reactjs-3811028/blob/02_03e/frontend/src/index.css

/** @type {import('tailwindcss').Config} */ export default { content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { extend: {}, }, plugins: [], };

src/index/css

delete everything 

add ad dbelow

@tailwind base; @tailwind components; @tailwind utilities; .active { @apply font-bold; }

=

"dev": "vite --port=3000",

"scripts": { "dev": "vite --port=3000", "build": "vite build", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" },

==

run

npm run dev at cd frontend

http://localhost:3000/


create

at src/pages

home.jsx

about.jsx

About.jsx

export default function About() {

    return (

        <div>

            <h1>About Page</h1>

            <p>Welcome to the about page!</p>

        </div>

    );

}


at Home.jsx

export default function Home() {

    return (

        <div>

            <h1>Welcome to my blog</h1>

            <p>Check out my latest posts below</p>

        </div>

    );

}

in index.html change title to

laravel react blog

index.html


<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>laravel+react blog</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

to see in about and home in browser

to use navigation

install react-router-dom

npm install react-router-dom

remove everything from app.tsx

import routes and aobut page ,

then write route paths


import "./App.css";

import { Routes, Route } from "react-router-dom";
import About from "./Pages/About";
import Home from "./Pages/Home";

function App() {
return (
<div className="w-3/5 mx-auto my-10">
<Navigation />
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</div>
);
}

export default App;

==

navigation.jsx

import { NavLink } from "react-router-dom";

export default function Navigation() {
return (
<nav className="pb-5 mb-5 border-b">
<ul className="flex justify-end space-x-5">
<li>
<NavLink to="/">Home</NavLink>
</li>
<li>
<NavLink to="/about">About</NavLink>
</li>
</ul>
</nav>
);
}


=s

App.tsx

import "./App.css";
import Navigation from "./Components/Navigation";
import { Routes, Route } from "react-router-dom";
import About from "./Pages/About";
import Home from "./Pages/Home.jsx";

function App() {
return (
<div className="w-3/5 mx-auto my-10">
<Navigation />
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</div>
);
}

export default App;

=


omdex.css

.active {
@apply font-bold;
}

==

some open json plac holders

https://jsonplaceholder.typicode.com/


in home.jsx

we will usestate

import this

axios import this

directly we will store to state

const [posts, setPosts] = useState([]);

destructured array

after dom loads we will useeffect

like mounted in vue

useEffect(() => {

        axios

            .get("https://jsonplaceholder.typicode.com/posts")

            .then((response) => {

                setPosts(response.data);

            })

            .catch((error) => {

                console.error("Error fetching data:", error);

            });

    }, []);

use for loop or map method

we get data and loop over thios

return (

        <div>

            <h1 className="my-5 text-xl font-semibold text-center">

                Welcome to My Blog

            </h1>


            {posts &&

                posts.map((post) => (

                    <div

                        key={post.id}

                        className="p-5 my-5 border rounded-md shadow-sm text-left"

                    >

                        <h2 className="mb-5 font-bold">{post.title}</h2>


                        <p>{post.body}</p>

                    </div>

                ))}

        </div>

    );


totally

import { useState, useEffect } from "react";
import axios from "axios";

export default function Home() {
const [posts, setPosts] = useState([]);

useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then((response) => {
setPosts(response.data);
})
.catch((error) => {
console.error("Error fetching data:", error);
});
}, []);

return (
<div>
<h1 className="my-5 text-xl font-semibold text-center">
Welcome to My Blog
</h1>

{posts &&
posts.map((post) => (
<div
key={post.id}
className="p-5 my-5 border rounded-md shadow-sm text-left"
>
<h2 className="mb-5 font-bold">{post.title}</h2>

<p>{post.body}</p>
</div>
))}
</div>
);
}

npm install axios

if u need u canisntall

above change as pages component

copy above code to posts/index.jsx

remove default and write as

export function Index() {

everything movied to posts

so no ned at home.jsx

simply import component and write at that place


import { Index as Posts } from "../Pages/Posts/Index";

<Posts />

code

import { Index as Posts } from "../Pages/Posts/Index";
export default function Home() {
return (
<div>
<h1 className="my-5 text-xl font-semibold text-center">
Welcome to My Blog
</h1>

<Posts />
</div>
);
}

\ at posts/index.jsx


import { useState, useEffect } from "react";
import axios from "axios";

export function Index() {
const [posts, setPosts] = useState([]);

useEffect(() => {
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then((response) => {
setPosts(response.data);
})
.catch((error) => {
console.error("Error fetching data:", error);
});
}, []);

return (
<div>
{posts &&
posts.map((post) => (
<div
key={post.id}
className="p-5 my-5 border rounded-md shadow-sm text-left"
>
<h2 className="mb-5 font-bold">{post.title}</h2>

<p>{post.body}</p>
</div>
))}
</div>
);
}

==

in app service provder

boot method

JsonResurce::withoutwrapping();


without data [] it will get


createing new post


create new route

at app.jsx


<Route path="post/create" element={<PostCreate />} />

import PostCreate from "./Pages/Posts/Create";

=

import state,axios, then navigate

means after route to

ist declare varaibles like state

then write function what happens after submit


import { useState } from "react";
import axios from "axios";
import { Link, useNavigate } from "react-router-dom";

export default function Create() {
const navigateTo = useNavigate();
const [title, setTitle] = useState("");
const [author, setAuthor] = useState("");
const [body, setBody] = useState("");

const handleSubmit = async (e) => {
e.preventDefault();
try {
await axios.post("http://linkedin-blog.test/api/posts", {
title,
author,
body,
});
setTitle("");
setAuthor("");
setBody("");
navigateTo("/");
} catch (error) {
console.error("Error creating post:", error);
}
};

return (
<form onSubmit={handleSubmit}>
<div className="flex flex-col space-y-8 text-left">
<h1 className="mx-auto text-xl">Create a new post</h1>
<label>
Title
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
className="block w-full rounded-md border-0 p-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-purple-200 sm:text-sm sm:leading-6"
/>
</label>

<label>
Author
<input
type="text"
value={author}
onChange={(e) => setAuthor(e.target.value)}
className="block w-full rounded-md border-0 p-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-purple-200 sm:text-sm sm:leading-6"
/>
</label>

<label>
Main content
<textarea
value={body}
onChange={(e) => setBody(e.target.value)}
className="block w-full rounded-md border-0 p-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-purple-200 sm:text-sm sm:leading-6"
/>
</label>
</div>

<div className="flex">
<Link
to="/"
className="inline-block px-4 py-2 mt-4 text-black border rounded-md hover:bg-gray-200"
>
Cancel
</Link>
<button
type="submit"
className="px-4 py-2 mt-4 ml-4 text-white bg-purple-500 rounded-md hover:bg-purple-600"
>
Create Post
</button>
</div>
</form>
);
}


=

updating a post


for to show newsest posts first

slice and reverse method

{posts &&
posts.slice().reverse().

update an existing post

https://github.com/LinkedInLearning/building-a-website-with-laravel-php-and-reactjs-3811028/blob/02_08e/frontend/src/Pages/Posts/Create.jsx

to navigate to particular post we ise link

<Link
to={`posts/update/${post.id}`}
state={post}
className="px-4 py-2 text-white bg-purple-500 rounded-md hover:bg-purple-600"
>
Edit Post
</Link>


=

 <Route path="posts/update/:id" element={<Update />} />

useLocatio from react router dom

it containes state information, about the route inculde state

tha we passed from previous route

{location.state.title} get dynamically post name

update post

import { useState } from "react";
import axios from "axios";
import { Link, useNavigate, useLocation } from "react-router-dom";

export default function Create() {
const location = useLocation();
const navigateTo = useNavigate();
const [title, setTitle] = useState(location.state.title);
const [author, setAuthor] = useState(location.state.author);
const [body, setBody] = useState(location.state.body);

const handleSubmit = async (e) => {
e.preventDefault();
try {
await axios.put(
`https://jsonplaceholder.typicode.com/posts/${location.state.id}`,
{
title,
author,
body,
}
);
navigateTo("/");
} catch (error) {
console.error("Error creating post:", error);
}
};

return (
<form onSubmit={handleSubmit}>
<div className="flex flex-col space-y-8 text-left">
<h1 className="mx-auto text-xl">
Update {location.state.title}
</h1>
<label>
Title
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
className="block w-full rounded-md border-0 p-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-purple-200 sm:text-sm sm:leading-6"
/>
</label>

<label>
Author
<input
type="text"
value={author}
onChange={(e) => setAuthor(e.target.value)}
className="block w-full rounded-md border-0 p-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-purple-200 sm:text-sm sm:leading-6"
/>
</label>

<label>
Main content
<textarea
value={body}
onChange={(e) => setBody(e.target.value)}
className="block w-full rounded-md border-0 p-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-purple-200 sm:text-sm sm:leading-6"
/>
</label>
</div>

<div className="flex">
<Link
to="/"
className="inline-block px-4 py-2 mt-4 text-black border rounded-md hover:bg-gray-200"
>
Cancel
</Link>
<button
type="submit"
className="px-4 py-2 mt-4 ml-4 text-white bg-purple-500 rounded-md hover:bg-purple-600"
>
Update Post
</button>
</div>
</form>
);
}

call the delete and delete method

    onClick={() => handleDeletePost(post.id)}

const handleDeletePost = async (postId) => {

        const shouldDelete = window.confirm(

            "Are you sure you want to delete this post?"

        );


        if (!shouldDelete) {

            return;

        }


        try {

            await axios.delete(`http://linkedin-blog.test/api/posts/${postId}`);


            setPosts((prevPosts) =>

                prevPosts.filter((post) => post.id !== postId)

            );

        } catch (error) {

            console.error("Error deleting post:", error);

        }

    };

import { useState, useEffect } from "react";
import axios from "axios";
import { Link } from "react-router-dom";

export function Index() {
const [posts, setPosts] = useState([]);

useEffect(() => {
axios
.get("http://linkedin-blog.test/api/posts")
.then((response) => {
setPosts(response.data);
})
.catch((error) => {
console.error("Error fetching data:", error);
});
}, []);

const handleDeletePost = async (postId) => {
const shouldDelete = window.confirm(
"Are you sure you want to delete this post?"
);

if (!shouldDelete) {
return;
}

try {
await axios.delete(`http://linkedin-blog.test/api/posts/${postId}`);

setPosts((prevPosts) =>
prevPosts.filter((post) => post.id !== postId)
);
} catch (error) {
console.error("Error deleting post:", error);
}
};

return (
<div>
<div className="flex">
<Link
to="/posts/create"
className="px-4 py-2 mt-4 text-white bg-purple-500 rounded-md hover:bg-purple-600"
>
Create new post
</Link>
</div>

{posts &&
posts
.slice()
.reverse()
.map((post) => (
<div
key={post.id}
className="p-5 my-5 text-left border rounded-md shadow-sm"
>
<h2 className="mb-5 font-bold">{post.title}</h2>
<p className="font-bold">{post.author}</p>

<p>{post.body}</p>

<div className="space-x-5 space-y-5">
<Link
to={`posts/update/${post.id}`}
state={post}
className="px-4 py-2 text-white bg-purple-500 rounded-md hover:bg-purple-600"
>
Edit Post
</Link>

<button
onClick={() => handleDeletePost(post.id)}
className="px-4 py-2 text-white bg-gray-400 rounded-md hover:bg-gray-500"
>
Delete Post
</button>
</div>
</div>
))}
</div>
);
}

=

show

location.


inertia js

=

No comments:

Post a Comment

server laravel application

 asset_url = domain/public chmod -R 755 public/admin/ composer dump-autoload get the application from hostinger