Skip to content

Commit

Permalink
V1 Completed
Browse files Browse the repository at this point in the history
  • Loading branch information
AvilaKevin committed May 18, 2023
1 parent 478e11d commit 4747987
Show file tree
Hide file tree
Showing 33 changed files with 1,261 additions and 1,623 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ yarn-debug.log*
yarn-error.log*

/serverYoutubeClone/.env
/YoutubeClone/.env
/serverYoutubeClone/node_modules/
/YouTubeClone/node_modules/
6 changes: 6 additions & 0 deletions YouTubeClone/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiKey = "AIzaSyBs_pDUBFRKhVwLvQcpYiEw7_KHfGdNj6A"
authDomain = "video-7e86b.firebaseapp.com"
projectId = "video-7e86b"
storageBucket = "video-7e86b.appspot.com"
messagingSenderId = "1025848928851"
appId = "1:1025848928851:web:406e7ec32d52916f92b4a6"
14 changes: 7 additions & 7 deletions YouTubeClone/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions YouTubeClone/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.2.3",
"axios": "^1.4.0",
"firebase": "^9.16.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
Expand Down Expand Up @@ -47,5 +47,5 @@
"last 1 safari version"
]
},
"proxy": "https://localhost:8800/api/"
"proxy": "https://localhost:8000/api/"
}
9 changes: 0 additions & 9 deletions YouTubeClone/src/components/Card.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,13 @@ const Info = styled.div`


const Card = ({ type, video }) => {
// Se crea un usestate para capturar y almacenar la informacion de nuestra api.
const [channel, setChannel] = useState({});

// // Se crea un use efect pa q se ejecute una funcion cuando se refresque la pg y ejecute la funcion de capturar la informacion del canal.

useEffect(() => {
// Esta funcion captura los datos de nuestra api y los pasa a nuestro estado del componente
// se crea la funcion de esta manera ya que useEffect no permite poner async
const fetchChannel = async () => {
// con la biblioteca de axios se solicita la informacion de nuestra api
// se extrae el id del usuario con video.userId para recogerlo como parametro
const res = await axios.get(`/users/find/${video.userId}`);
// Se almacena la informacion en el estado.
setChannel(res.data);
};
// Se ejecuta nuestra funcion
fetchChannel();
}, [video.userId]);

Expand Down
10 changes: 2 additions & 8 deletions YouTubeClone/src/components/Comment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,25 +81,19 @@ const Options = styled.div`
`;

function Comment({ comment, fetchComments }) {
// Se crean los estados para almacenar la informacion que se va a extraer del servidor
const [channel, setChannel] = useState({});

// Estado del div
const [showDiv, setShowDiv] = useState(false);

const { currentUser } = useSelector((state) => state.user);

useEffect(() => {
const fetchComment = async () => {
// Se busca el id del usuario dentro de las propiedades de los comentarios
const res = await axios.get(`/users/find/${comment.userId}`);
setChannel(res.data);
};

fetchComment();
}, [comment.userId]);

// Cierra y muestra las opciones del comentario

const handleOptions = () => {
if (showDiv === true) {
setShowDiv(false)
Expand All @@ -108,7 +102,7 @@ function Comment({ comment, fetchComments }) {
}
};

// Borra el comentario
// DELETE A COMMENT
const handleDelete = async () => {
await axios.delete(`/comments/${comment._id}`);
fetchComments()
Expand Down
24 changes: 0 additions & 24 deletions YouTubeClone/src/components/Comments.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,64 +96,41 @@ const BCancel = styled.button`
`;

function Comments({ videoId }) {
// Para acceder a las propiedades de nuestro estado, se hace uso de useSelector, en este caso se esta accediendo a currentUser que esta dentro de user para extraer algunas de sus propiedades
const { currentUser } = useSelector((state) => state.user);
const { currentVideo } = useSelector((state) => state.video);

// Se crean los estados para almacenar la informacion que se va a extraer del servidor
const [comments, setComments] = useState([]);

// Se crea un estado que muestra el div
const [showDiv, setShowDiv] = useState(false);

// Se crea un estado q habilita el boton cuando se esccribe algo en el input
const [inputValue, setInputValue] = useState('');

// Se encarga de traer y actualizar el estado de los comentarios
const fetchComments = async () => {
try {
// Se traen los comentarios del video usando el id del video
const res = await axios.get(`/comments/${videoId}`);

// Se almacena la info en nuestro estado
// .data hace referencia a la propiedad de un objeto
setComments(res.data);
} catch (err) { };
};

// El useEffect se ejecutara cada vez que se cambie de id de video
useEffect(() => {
fetchComments();
}, [videoId]);

// Cuando se da click en el input se muestra el div
const handleInput = () => {
setShowDiv(true);
};

// Cuando se escribe algo en el input se habilita el boton
const handleInputChange = (event) => {
setInputValue(event.target.value);
};

// Cierra el input
const handleBCancel = () => {
setShowDiv(false);
// Se limpia el input
setInputValue("");
};

// Esta envia el comentario realizado al server y actualiza el estado
const handleComment = async () => {
// Se crea un objeto que almacena las propiedades del obj que se nesecita para crear un comentario
const commentObj = { "desc": inputValue, "videoId": currentVideo._id };
// Se envia el obj creado al server
await axios.post("/comments", { ...commentObj });
// Se actualiza el estado de comentarios
fetchComments();
// Se limpia el input
setInputValue("");
// Se cierra el modal
setShowDiv(false);
};

Expand All @@ -173,7 +150,6 @@ function Comments({ videoId }) {
</CommentLink>
</StyledLink>}
</NewComment>
{/* Si showDiv es true entonces se renderiza el componente, de lo contrario no se renderiza nada */}
{showDiv && <FocusComment>
<div></div>
<div>
Expand Down
3 changes: 1 addition & 2 deletions YouTubeClone/src/components/Menu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Link } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { logout } from '../redux/userSlice';

// Icons
// ICONS
import YourVideosLogo from '../img/YouTubeLogo.png'
import HomeIcon from '@mui/icons-material/Home';
import ExploreOutlinedIcon from "@mui/icons-material/ExploreOutlined";
Expand Down Expand Up @@ -96,7 +96,6 @@ const Title = styled.h2`

const Menu = ({ darkMode, setDarkMode }) => {
const { currentUser } = useSelector((state) => state.user);
// Se inicializa nuestra funcion dispatch para poder hacer uso de los estados de nuestro store
const dispatch = useDispatch();

const handleLogOut = () => {
Expand Down
5 changes: 0 additions & 5 deletions YouTubeClone/src/components/Recommendation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,12 @@ const Container = styled.div`
flex: 2;
`;

// Dependiendo de los tags de nuestro video vamos a capturar los traer los recomendados
const Recommendation = ({ tags }) => {
// Se almacena la informacion consultada de nuestra bd
const [videos, setVideos] = useState([]);

// Cuando corramos este componente vamos a traer los videos
useEffect(() => {
const fetchVideos = async () => {
// se hace una express query usando los tags a nuestro server
const res = await axios.get(`/videos/tags?tags=${tags}`);
// Se pasa la informacion capturada a nuestro estado
setVideos(res.data);
};
fetchVideos();
Expand Down
5 changes: 0 additions & 5 deletions YouTubeClone/src/components/Share.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ const Copy = styled.button`
font-weight: 500;
`;

// Se recibe la prop de este modo pa poderla manipular mas adelante
function Share({ setIsSharing }) {
// Pa validar en que video se esta actualmente se hace uso de redux el cual accede al objeto video y nos trae esa informacion
const { currentVideo } = useSelector((state) => state.video);

const videoLink = `https://localhost:3000/video/${currentVideo._id}`;
Expand All @@ -96,13 +94,10 @@ function Share({ setIsSharing }) {
<Exit onClick={() => setIsSharing(false)} />
<Title>Share</Title>
<ShareIcons>
{/* De esta forma agregamos los iconos para compartir */}
<div>
<FacebookShareButton
// En este campo va la url que deseamos compartir
url={`https://localhost:3000/video/${currentVideo._id}`}
>
{/* Aqui se personaliza el estilo del boton */}
<FacebookIcon size={60} round />
</FacebookShareButton>
<p>Facebook</p>
Expand Down
29 changes: 2 additions & 27 deletions YouTubeClone/src/components/Upload.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,48 +74,32 @@ const Label = styled.label`
const Upload = ({ setOpen }) => {
const [img, setImg] = useState(undefined);
const [video, setVideo] = useState(undefined);

// Estos estados mostraran la barra de progreso al momento de subir un video
const [imgPerc, setImgPerc] = useState(0);
const [videoPerc, setVideoPerc] = useState(0);

// Estos estados almacenan la info de los inputs
const [inputs, setInputs] = useState({});
const [tags, setTags] = useState([]);

const navigate = useNavigate();

// Se crea una funcion que separa los tags por , y los almacena en el estado
const handleTags = (e) => {
setTags(e.target.value.split(","))
};

// Se crea esta funcion que permite almacenar de forma facil y rapida varios inputs y componentes
const handleChange = (e) => {
setInputs((prev) => {
// ...prev, cada vez que se intente cambiar la descripcion, esto tomara el valor previo de title y desc
// [e.target.name]: cambia el valor de prev
// e.target.value es el nuevo valir de prev
return { ...prev, [e.target.name]: e.target.value };
});
};

// Se crea una funcion que se encarga en subir el video y la img a firebase
const uploadFile = (file, urlType) => {
// esto almacena la info
const storage = getStorage(app);
// Esto evitara que hayan archivos con el mismo nombre
const fileName = new Date().getTime() + file.name;
const storageRef = ref(storage, fileName);
const uploadTask = uploadBytesResumable(storageRef, file);

// Listen for state changes, errors, and completion of the upload.
uploadTask.on(
'state_changed',
(snapshot) => {
// Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
// si urlType es imgUrl entonces setImgPerc(progress) si no setVideoPerc(progress);
urlType === "imgUrl" ? setImgPerc(Math.round(progress)) : setVideoPerc(Math.round(progress));
switch (snapshot.state) {
case 'paused':
Expand All @@ -130,7 +114,7 @@ const Upload = ({ setOpen }) => {
},
(error) => { },
() => {
// Upload completed successfully, now we can get the download URL

getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setInputs((prev) => {
return { ...prev, [urlType]: downloadURL };
Expand All @@ -140,33 +124,24 @@ const Upload = ({ setOpen }) => {
);
};

// Cuando subamos el video se ejecutara esta funcion que ejecuta uploadFile el cual sube el archivo a firebase
useEffect(() => {
// si hay un video llama esta funcion
video && uploadFile(video, "videoUrl");
}, [video]);

// Cuando subamos la img se ejecutara esta funcion que ejecuta uploadFile el cual sube el archivo a firebase
useEffect(() => {
// si hay una img llama esta funcion
img && uploadFile(img, "imgUrl");
}, [img]);

// Envia el video y la imagen subida a nuestra bd
const handleUpload = async (e) => {
// evita el refresco de nuestra pg
e.preventDefault();
const res = await axios.post("/videos", { ...inputs, tags })
// se cierra el modal

setOpen(false)
// nos envia la pesta;a de navigate si la respuesta del server es 200
res.status === 200 && navigate(`/video/${res.data._id}`)
}

return (
// Este ocupara toda la pantalla
<Container>
{/* Y este sera como un small box */}
<Wrapper>
<Close onClick={() => setOpen(false)}>X</Close>
<Title>Upload a New Video</Title>
Expand Down
12 changes: 6 additions & 6 deletions YouTubeClone/src/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { getAuth, GoogleAuthProvider } from "firebase/auth";

// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyBs_pDUBFRKhVwLvQcpYiEw7_KHfGdNj6A",
authDomain: "video-7e86b.firebaseapp.com",
projectId: "video-7e86b",
storageBucket: "video-7e86b.appspot.com",
messagingSenderId: "1025848928851",
appId: "1:1025848928851:web:406e7ec32d52916f92b4a6"
apiKey: process.env.apiKey,
authDomain: process.env.authDomain,
projectId: process.env.projectId,
storageBucket: process.env.storageBucket,
messagingSenderId: process.env.messagingSenderId,
appId: process.env.appId
};

// Initialize Firebase
Expand Down
11 changes: 0 additions & 11 deletions YouTubeClone/src/pages/Home.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,18 @@ const Container = styled.div`
`;

const Home = ({ type }) => {
// Se crea un usestate para capturar y almacenar la informacion de nuestra api, la cual seran videos random.
const [videos, setVideos] = useState([]);

// Se crea un use efect pa q se ejecute una funcion cuando se refresca la pg y ejecute la funcion de captura de videos.

useEffect(() => {
// Esta funcion captura los datos de nuestra api y los pasa a nuestro estado en el front-end
// se crea la funcion de esta manera ya que useEffect no permite poner async
const fetchVideos = async () => {
// con la biblioteca de axios se solicitan los videos random utilizando el metodo get
// se utiliza la prop type para hacer esta funcion dinamica y ejecute tambien los de mas metodos de video
const res = await axios.get(`/videos/${type}`);
// Se almacena los videos random en el estado.
setVideos(res.data);
};
// Se ejecuta nuestra funcion
fetchVideos();
}, [type]);

return (
<Container>
{/* Se crea una key para q react pueda identificar los elementos q se renderizan
se envia como prop a nuestra card el video para poder usarlo en el componente card*/}
{videos.map((video) => (
<Card key={video._id} video={video} />
))}
Expand Down
Loading

0 comments on commit 4747987

Please sign in to comment.