Skip to content

RodrigoMvs123/CRM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 

Repository files navigation

CRM

Clone

Final Code https://github.com/kubowania/monday-crm-clone

https://raw.githubusercontent.com/RodrigoMvs123/CRM/main/README.md https://github.com/RodrigoMvs123/CRM/blame/main/README.md

R: Microsoft Original Documentation https://docs.microsoft.com/en-us/dotnet/api/microsoft.xrm.tooling.connector.crmserviceclient.clone?view=dataverse-sdk-latest
https://docs.microsoft.com/en-us/power-apps/developer/data-platform/xrm-tooling/use-crmserviceclient-constructors-connect https://docs.microsoft.com/en-us/power-apps/developer/data-platform/xrm-tooling/sample-tpl-crmserviceclient

🛑 Build a Monday CRM Clone with GET POST PUT DELETE Requests | React + NodeJS + useContext Hook

To Build a CRM Clone with “GET”, “POST”, “PUT”, “DELETE”, Requests | React + NodeJS + useContext, Hook.

Final Code: https://github.com/kubowania/monday-crm-clone

https://auth.cloud.datastax.com/auth/realms/CloudUsers/protocol/openid-connect/registrations?client_id=auth-proxy&response_type=code&scope=openid+profile+email&redirect_uri=https://astra.datastax.com/welcome&utm_source=youtube&utm_medium=referral&utm_campaign=ania-kubow&utm_term=frontend-devplay&utm_content=monday-crm-clone

To Add New Project React Package.json [ Script ]

1 - // To Delete Index JS File JS File To Delete Line 01 // Logo Function Const To Delete To Delete // Header To Delete Index.Css File

2- // Context.js Project Clone SRC // Source Directory New / Directory JavaScript File context.js import {createContext} from “react” const CategoryContexts = createContext ({ categories=null, setCategories: () => {] }) export default CategoriesDefault New JavaScript File

3 - // AvatarDisplay Component Import blankAvatar from '../ images / blank-profile-avatar.png ' const AvatarDisplay = ( { ticket } ) = > { return (

className = "avatar-container"
{
) } export default AvatarDisplay // - Image Directory Components New New JavaScript File

4 - // DeleteBlock Component import axios from ‘axios’ const DeleteBlock = (documentId ) = > { const response await axios.delete(‘http://localhost:8000/tickets/${documentId}/’) const success = response.status == 200
if (success) window.location.reload() const deleteticket = async () => { } return (

className”delete-icon” onClick {deleteticket}
) } export default DeleteBlock Components New New JavaScript File Components New New JavaScript File

5 - // Nav Component import logo from ‘../import/crm-logo-png’ import { useNavigate } from ‘react-router-dom const = Nav () => { const navigate = useNavigate () return (

navigate (‘/ticket’ )} >+
navigate (‘/ticket’ )} > <<
“logo”/
) } export default Nav.js

6 - // PriorityDisplay Component const PriorityDisplay = ( { priority } ) = > { return (

=1 ? ‘rgb(253, 253, 150)’ : ‘ ‘ } } >☆

=2 ? ‘rgb(253, 253, 150)’ : ‘ ‘ } } >☆

=3 ? ‘rgb(253, 253, 150)’ : ‘ ‘ } } >☆

=4 ? ‘rgb(253, 253, 150)’ : ‘ ‘ } } >☆

=5 ? ‘rgb(253, 253, 150)’ : ‘ ‘ } } >☆

) } export default PriorityDisplay Components New New JavaScript File

7 - // ProgressDisplay Component const ProgressDisplay = ( { progress } ) = > { return (

className=”progress-bar”
style={{ witdh:progress + ‘%’ }} className=”progressindicator”
) } export default ProgressDisplay Components New New JavaScript File

8 - // StatusDisplay Component const StatusDisplay = ( { status } ) => { const getColor = ( status ) = > let color switch = ( status ) { case ‘done’: color: ‘rgb ( 186, 255, 201 )’
break case ‘working on it’: color = color ‘ rgb ( 255, 223, 186 )’ break case: ‘stuck’ : color = ‘ rgb ( 255, 179, 186 )’ break default: color: ‘ rgb ( 186, 255, 255 )’ } return color } return (

className=”status-display” style= {{ backgroundcolor: getColor(status)}} { status }
) } Components New New JavaScript File

9 - // TicketCardjs. Component import { Link } from ‘react-from-dom’ import AvatarDisplay from “/.AvatarDisplay” import StatusDisplay from “/.StatusDisplay” import PriorityDisplay from “/.PriorityDisplay” import ProgressDisplay from “/.ProgressDisplay” import DeleteBlock from “/.DeleteBlock”
const TicketCard = ( { color, filteredTicket } ) = > { return (

className= “ ticket color ” style= {{backgroundColor: color}}>

filteredTicket.title

) }

export default TicketCard.js Pages New New JavaScript File

10 - // Dashboard Component const Dashboard = ( ) { return (

Dashboard
) } export default Dashboard Pages New New JavaScript File

11 - // TicketPage Component

import { use State, useContex, useEffect } from ‘react’ import {useNavigate, useParams} from ‘react-router ’ import axios from ‘axios’ import CategoriesContex from ‘../context’ const TicketPage = ({editMode} ) = > { const {fromData, setFormData = useState ( status: ‘not started’ , progress: 0; category: categories[0], timestamp: new: new Date (). toISOString () ) } const {categories, setCategories} = useContex (CategoriesContex) const navigate = useNavigate () let { id } = useParams () const handleSubmit = sync (e) = > { e.preventDefault () if (editMode) { const response = await axios.put(‘http://localhost:8000/tickets/${id}’ { data:formData }) const success = response.status === 200 if (success) navigate {‘/’} } } if ( !editmode ) { const response = await axios.post (‘https://localhost:8000/tickets’, {
formData }) const success = response.status === 200 if (success) navigate {‘/’} } } } const fetchData = () => async { const response = await axios.get(‘http://localhost:8000/tickets/${id}’) setFormData(response.data.data) } use effect (()) => { if (editMode) fetchData() }, []) const handleChange = () = > { const value = e.target.value const name = e.target.name setFormData ((prevState) = > ({ …prevState, [name]: value }) ) } { editMode && <> <input type = “ range ” id = “progress” name = “progress” value= {formData.progress} min=”0” max=”100” onChange={handleChange} /> Progress Status <select name=”status” value={formData.status} onChange={habdleChange}

Done Working on it Stuck Not Started }
{formData.avatar && ) “img-preview”/ )}
) } console.log (formData) return (

{ editMode ? ‘ Update your Ticket’ : Create a Ticket }

Title Description Category categories? .map ( category, _index) => ( ))} New Category Priority 1
label htmlFor=”priority-1”>1 Priority 1
Priority 2
Priority 3
Priority 4
5
export default TicketPage Pages New New JavaScript File

12 - // Appjs. Terminal npm i react - router - dom // App.js import { BrowserRouter, Route, Routes } from ‘ react - router - dom ’ // package.json const Class Name = ( ) { return (

App
) } export default App // SoftWare Version package.json “ react - router - dom ”: “ 6.2.2 ”, “ react - router - dom ”: “ 6.2.1 ”, Terminal To Change SoftWare Version npm i

13 - //App.js import { BrowserRouter, Route, Routes } from ‘ react - router - dom ’ // package.json import { useState } from ‘react’ import Nav from ‘ ./ components / Nav ’ import Dashboard from ‘ ./ pages/Dashboard ’ import TicketPage from ‘ ./ pages/TicketPage ’ import CategoriesContext from ‘../context’ const app => ( ) { const [categories, setCategories] = useState(null)
const value = { categories, setCategories } return ( < div class Name = “ app ” > <CategoriesContext,Provider value = {value}>

}/> }/> }/>
) } export default App }

14 - // Dashboard.JS Categories import {useState, useEffect, useContex } from ‘react’ import Ticket Card from ‘ ../ components/TicketCard ’ import axios from ‘axios’ import CategoriesContext from ‘../context’ const Dashboard = ( ) const {tickets, setTickets } = useState ( null ) const { categories, setCategories } = useContex (categoriesContex) useEffect (async () = > { const response = await axios.get(‘http://localhosto:8000/tickets’) const dataObject response.data.data const arreysOfkeys = object.keys(dataObject)
const arreyOfdata = object.keys(dataObject) map(key)=>dataObject[key]) const formattedArray = [] arreyOfKeys.forEach(key, index) => { const formattedData = {... arrayOfData [index] } formattedData ‘documentId’ = key formattedArray.push (formattedData) })
setTickets(formattedArray) }, []) useEffect (() => ) { setCategories ([...new Set (tickets?.map ({category}) =>cayegory)]) }, [tickets] ) console.log(categories) const tickets = [ { category: ‘ Q1 2022 ’, color: ‘red’, title: ‘ NFT Safety 101 Video’
owner: ‘ Rodrigo ’ avatar: ‘ 12HR+ YouTube Coding Bootcamp 2021! ’, status: ‘ done ’, priority: ‘ 5 ’, progress: ‘ 40 ’, description: ‘ Make a video showcase how to work with NFTs safety, including how to know if one is not genuine ’, timestamp: ‘ 2022 - 02 - 11T07:36:17+0000 ’ }, { category: ‘ Q1 2022 ’, color: ‘red’, title: ‘ Bild and Sell AI Model’
owner: ‘ Rodrigo ’ avatar: ‘ 12HR+ YouTube Coding Bootcamp 2021! ’, status: ‘ working on it ’, priority: ‘ 2 ’, progress: ‘ 70 ’, description: ‘ Make a video about AI ’, timestamp: ‘ 2022 - 02 - 13T07:36:17+0000 ’ category: ‘ Q2 2022 ’, color: ‘blue’, title: ‘ Biuld a bot’
owner: ‘ Rodrigo ’ avatar: ‘ 12HR+ YouTube Coding Bootcamp 2021! ’, status: ‘ done ’, priority: ‘ 3 ’, progress: ‘ 10 ’, description: ‘ Make a video showcase how to work with NFTs safety, including how to know if one is not genuine ’, timestamp: ‘ 2022 - 02 - 11T07:36:17+0000 ’ } ] const colors = [ ‘rgb(255,179,186)’, ‘rgb(255,233,186)’, ‘rgb’(255,255,186), ‘rgb(186,255,201)’, ‘rgb(186,255,255)’, ] const uniqueCategories = [ ...new Set(tickects?.map(({category}) => category))) ] return (

My Projects

{tickets && uniqueCategories?.map({uniqueCategory, categoryIndex) => (

uniqueCategory

{tickets.filter(ticket => ticket.category === uniqueCategory ) .map ( filteredTicket, _index) => ( )) }
) ) }
export default Dashboard // inspect Pages New New JavaScript File

15 - // Index.css

html, body { margin: 0; padding: 0; font - family: ‘ Trebuchet MS ’, Arial, sans - serif; } .app { display: flex; }

link{

text-decoration: none; color: rgb (46, 46, 46); } /----- Nav —--/ nav { height: 100vh; background-color: rgb ( 43, 43, 63 ); color: rgb ( 255, 255, 255 ) ; text- align: center; display: flex; flex-direction: column; justify-content: space-between;
} nav .logo-conteiner, nav controls-conteiner { padding: 40px 25px; display: flex; flex-direction: column; } nav .logo-conteiner, width 20px; } nav .icon { color: rgb ( 255, 255, 255 ); } /----- Dashboard —--/ .dashboard { padding: 30px; width: 100%; } .dashoboard ticket-cointainer { height: 80vh; overflow: scroll; } /----- TicketCard —--/ .Ticket-card { display: flex; width: 100%; } .ticket-card # { display: flex; width: 100%; } .ticket-card # > ☆ { background-color = rgb (211,211,211); margin: 2px; padding 30px; width 100%; display: flex; align-items: center; } .ticket-card .ticket-color { width: 15px !important ; Padding: 10px !important; margin: 2px; } .ticket-card .avatar-container { display: flex; justify-content: center; width: 80px; } .ticket-card .img-container { height: 50px; width: 50px; border-radius: 25px; overflow: hidden; .ticket-card .img-container img { width: 100px; } } .ticket-card .status-display { display: flex; justify-content: center; } .ticket-card .priority-display { display: flex; justify-content: center; } .ticket-card .priority-display .star-container { display: flex; } .ticket-card .priority-display .star-container h3 { margin: 7px; padding: 0px; } .ticket-card .progress-display { min-width: 200px; } .ticket-card .progress-bar { width: 100%; height: 30px; background-color: rgb(158, 158, 158 ); border-radious: 15px; overflow: hidden; } .ticket-card .progress-bar .progress-indicator { background-color: rgb( 104, 104, 175); height: 100%; } .ticket-card .delete-block { background-color: rgb (211, 211, 211); width: 50px; margin: 2px; display: flex; justify-content: center; align-items: center; } .ticket-card .delete-block.delete-icon { width: 2opx; height: 20px; border-radius: 10px; background-color: rgb (61, 61, 61); display: flex; justify-content: center; align-items: center; color: rgb (255, 255, 255) } /*—- Ticket Page —-- */ .ticket { padding; 30px; width:100px; } .ticket .ticket-container { width: 100%; display: flex; justify-content: center; }
.ticket form { display: flex; } .ticket form section { display: flex; flex-direction: column margin:10px; width: 500px; } .ticket form label { margin: 20px o o o; } .ticket form select .ticket form input { padding 10px; font-size: 15px; border-radius: 10px; border: 1.5px solid rgb 9 (218,218,218); margin: 5px; } .ticket form .multiple-input-container { margin: 20px 20 px 0; } Project Monday-clone SRC README.md New JavaScript File server.js Terminal: monday-clone % npm i express cors axios dotenv monday-clone % npm i nodemon Project Monday-clone SRC package.json npm i nodemon - - save-dev to change line 11: To change line 20 and 21: Project Monday-clone SRC package.json Terminal: % npm run start: backend

16 - // server.js const PORT = 8000 const express = require (‘express’) const cors = require (‘cors’)’ require (‘dotenv’). config () const axios = require (‘axios’) const app = express () app.use(cors()) app.use (express.json () ) const url = process.env.URL const token = process.env.ASTRA_TOKEN app.get(‘/tickets’, async ( res, res ) => { const options = { method ‘GET’, headers: { accepts: ‘applications/json’, ‘X-Cassandra-Token’: token, } } try { const response = await axios ( ‘${url}?page-size=20’, options ) rest.status(200).json(response.data) } catch ( err ) { console.log ( err) res.status ( 500 ).json({message:err}) } }) app.get(‘/tickets/:documentId’, async ( req,res ) => ) { const id = req.params.documentId const options = { method: ‘GET’, headers:{ accepts: ‘application.json’, ‘X-Cassandra-Token: token’, } } try { const response = await axios (‘${url}/${id}’), options res.status(200).json(response,data) } catch (err) { console.log ( err) res.status ( 500 ).json({message:err}) } }) app.post(‘/tickets’ , async ( req, res ) = > { const formData = req.form.body.formData const options - { method ‘POST’, headers: { accepts: ‘applications/json’, ‘X-Cassandra-Token’: token, ‘Content-Type’: ‘application.json’, }, data: formData } try { const response = await axios ( url. option ) res.status(200).json(response.data) } catch (err ) { console.log ( err) res.status ( 500 ).json({message:err}) } }) app.put(‘/tickets/:documentId’, async ( req,res ) => ) { const id = req.params.documentId const data = req.body.data const options = { method: ‘PUT’, headers:{ accepts: ‘application.json’, ‘X-Cassandra-Token: token’, }, data } try { const response = await axios (‘${url}/${id}’), options res.status(200).json(response,data) } catch (err) { console.log ( err) res.status ( 500 ).json({message:err}) } }) app.delete(‘/tickets/:documentId’, async(req, res)=>{ const id = req.params.documentId const options ={ method: ‘DELETE’, headers: { accepts: ‘applications/json’, ‘X-Cassandra-Token’ : token } } try { const response = await axios (‘${url}/${id}’), options res.status(200).json(response,data) } catch (err) { console.log ( err) res.status ( 500 ).json({message:err}) } } }) app.listen ( PORT, () = > console.log (‘server running on PORT’ + PORT ) ) to add an new task server.js New JavaScript File

17 // dummydate.js //
const tickets = [ { category: ‘ Q1 2022 ’, color: ‘red’, title: ‘ NFT Safety 101 Video’
owner: ‘ Rodrigo ’ avatar: ‘ 12HR+ YouTube Coding Bootcamp 2021! ’, status: ‘ done ’, priority: ‘ 5 ’, progress: ‘ 40 ’, description: ‘ Make a video showcase how to work with NFTs safety, including how to know if one is not genuine ’, timestamp: ‘ 2022 - 02 - 11T07:36:17+0000 ’ }, { category: ‘ Q1 2022 ’, color: ‘red’, title: ‘ Bild and Sell AI Model’
owner: ‘ Rodrigo ’ avatar: ‘ 12HR+ YouTube Coding Bootcamp 2021! ’, status: ‘ working on it ’, priority: ‘ 2 ’, progress: ‘ 70 ’, description: ‘ Make a video about AI ’, timestamp: ‘ 2022 - 02 - 13T07:36:17+0000 ’ category: ‘ Q2 2022 ’, color: ‘blue’, title: ‘ Biuld a bot’
owner: ‘ Rodrigo ’ avatar: ‘ 12HR+ YouTube Coding Bootcamp 2021! ’, status: ‘ done ’, priority: ‘ 3 ’, progress: ‘ 10 ’, description: ‘ Make a video showcase how to work with NFTs safety, including how to know if one is not genuine ’, timestamp: ‘ 2022 - 02 - 11T07:36:17+0000 ’ } ] const colors = [ ‘rgb(255,179,186)’, ‘rgb(255,233,186)’, ‘rgb’(255,255,186), ‘rgb(186,255,201)’, ‘rgb(186,255,255)’, ] //

18 - // .env URL = http://…// tickets / collections ASTRA_TOKEN = Astra CS:...//DBToken

Releases

No releases published

Packages