123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- /* const getGQL = url => (query,variables={}) =>
- fetch(url,{
- method:"POST",
- headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json',
- },
- body:JSON.stringify({query,variables})
- }).then((res) => res.json())
- .then((data) => {
- if(data.errors && !data.data){
- throw new Error(JSON.stringify(data.errors))
- } else{
- let value = Object.values(data.data);
- return value[0];
- }
- }) */
- //headers:{...{localStorage.authToken & {Autorization: `Bearer ${LocalStorage.authToken} : {}`}}}
- /* const getGQL = url =>{
- return async (query,variables={}) =>{
- let parametrs = {headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json',
- }}
- let authToken = localStorage.getItem("authToken")
- if(authToken){
- parametrs.headers.Authorization = "Bearer" + authToken
- }
- parametrs.body = JSON.stringify({query,variables})
- parametrs.method = "POST"
- let result = await fetch(url,parametrs)
- .then((res) => res.json())
- if("data" in result) {
- return result.data[Object.keys(result.data)[0]]
- } else if("errors" in result){
- throw new Error(JSON.stringify(result.errors))
- }
- }
- }
- const backendURL = 'http://shop-roles.asmer.fs.a-level.com.ua'
- const gql = getGQL('http://shop-roles.asmer.fs.a-level.com.ua/graphql'); */
- const getGQL = url =>
- (query, variables) => fetch(url, {
- method: 'POST',
- headers: {
- "Content-Type": "application/json",
- ...(localStorage.authToken ? {"Authorization": "Bearer " + localStorage.authToken} : {})
- },
- body: JSON.stringify({query, variables})
- }).then(res => res.json())
- .then(data => {
- if (data.data){
- return Object.values(data.data)[0]
- }
- else throw new Error(JSON.stringify(data.errors))
- })
- const backendURL = 'http://shop-roles.asmer.fs.a-level.com.ua'
- const gql = getGQL(backendURL + '/graphql')
- /* (async()=>{
- let data = await gql(`query login($login:String, $password:String){
- login(login:$login, password:$password)
- }`, {login:'Anon', password:'Anon'});
-
- localStorage.authToken = data;
-
- })(); */
- /*
- gql(`query login($login:String, $password:String){
- login(login:$login, password:$password)
- }`, {login:'Anon', password:'Anon'}) //login with gql function
- .then((data) => console.log(data)); */
-
- /// some queries but works not good
- /* query CoutCat{
- CategoryCount(query:"[{}]")
- }
-
- query findCategory {
- CategoryFind(query:"[{}]"){
- name
- goods{name,categories{name}}
- parent{parent{name}}
- }
- }
-
-
- mutation newGood($newGood:GoodInput){
- GoodUpsert(good:$newGood){
- name
- price
- description
- categories{name}
- }
- } */
- function promiseReducer(state={}, {type,name,status,payload,error}){
- /* delay1000:{status, payload,error}
- delay2000: {status, payload,error}*/
- if(!state){
- delay1000:{status,payload,error}
- delay2000:{status,payload,error}
- }
- if(type === 'PROMISE'){
- return{
- ...state,
- [name]:{status,payload,error}
- }
- }
- return state
- }
-
- function createStore(promiseReducer){
- let state = promiseReducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
- let cbs = [] //массив подписчиков
-
- const getState = () => state //функция, возвращающая переменную из замыкания
- const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
- () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
-
- const dispatch = action => {
- if (typeof action === 'function'){ //если action - не объект, а функция
- return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
- }
- const newState = promiseReducer(state, action) //пробуем запустить редьюсер
- if (newState !== state){ //проверяем, смог ли редьюсер обработать action
- state = newState //если смог, то обновляем state
- for (let cb of cbs) cb() //и запускаем подписчиков
- }
- }
-
- return {
- getState, //добавление функции getState в результирующий объект
- dispatch,
- subscribe //добавление subscribe в объект
- }
- }
- const combineReducers = (reducers) =>
- (state={},action) => {
- const newState = {}
- for(const [reduceName, reducer] of Object.entries(reducers)){
- let newSubState = reducer(state[reduceName],action);
- if(state[reduceName] !== newSubState){
- newState[reduceName] = newSubState
- }
- }
- if(Object.keys(newState).length){
- state = {...state, ...newState}
- }
- return state;
- }
-
- /* let store = createStore(promiseReducer);
- store.subscribe(()=>console.log(store.getState())); */
- const actionPending = name => ({name,type:"PROMISE",status:'PENDING'})
- const actionFulfiled = (name,payload) =>({name,type:"PROMISE",status:'FULFILLED',payload})
- const actionrRejected = (name,error) => ({name,type:"PROMISE",status:'REJECTED',error})
-
- const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
- /* store.subscribe(() => console.log(store.getState())); */
- /* store.dispatch(actionPending('delay1000'))
-
- //{ 1
- // delay1000: {status: 'PENDING'}
- //}
- delay(1000).then(result => store.dispatch(actionFulfiled('delay1000', result)))
- /* console.log(store.getState()); */
- //{ 3
- // delay1000: {status: 'FULFILLED', payload: 1000},
- // delay2000: {status: 'PENDING'}
- //}
-
- /* store.dispatch(actionPending('delay2000'))
- //{ 2
- // delay1000: {status: 'FULFILLED', payload: 1000},
- // delay2000: {status: 'PENDING'}
- //}
- delay(2000).then(result => store.dispatch(actionFulfiled('delay2000', result))) */
- //{ 4
- // delay1000: {status: 'FULFILLED', payload: 1000},
- // delay2000: {status: 'FULFILLED', payload: 2000}
- //} */
-
- const jwtDecode = token =>{
- try{
- let payload = JSON.parse(atob(token.split('.')[1]));
- return payload;
- } catch(e){
-
- }
- }
- console.log(jwtDecode(localStorage.getItem('authToken')));
-
- function authReducer(state,{type, token}){
- if(state === undefined){
- if(localStorage.authToken){
- type = 'AUTH_LOGIN';
- token = localStorage.authToken
- }
- }
- if(type === 'AUTH_LOGIN'){
- let payload = jwtDecode(token);
- if(payload){
- localStorage.authToken = token;
- return {token,payload}
- }
- }
- if(type === 'AUTH_LOGOUT'){
- localStorage.authToken = '';
- return {};
- }
- return state || {};
- }
-
- function cartReducer(state={},{type, good, count=1}){
-
- /* _id1: {count:1, good: {_id1,name,price,images}}
- _id2: {count:1, good: {_id2,name,price,images}}
- */
-
- if (type === 'CART_ADD'){
- /* if(good._id in state){
- return{
- ...state,
- [good._id]: {count:state[good._id].count+count,good}
- }
- }else{ */
- return{
- ...state,
- [good._id] : {count: count + (good._id in state ? state[good._id].count : 0),good}
- }
- }
-
-
- if (type === 'CART_CHANGE'){
- /* let _id1 = good._id;
- console.log(_id1); */
- return{
- ...state,
- [good._id]: {count:count,good:good}
- }
- }
- if (type === 'CART_DELETE'){
- /* const clone = {...state}
- delete clone[good._id]
- state = {...clone} */
- let {[good._id]: remove, ...newState} = state;
- return newState;
- }
- if (type === 'CART_CLEAN'){
- return {}
- }
- return state
- }
- const actionCartAdd = (good, count=1) => ({type:'CART_ADD', good, count})
- const actionCartChange = (good, count=1) => ({type:'CART_CHANGE',good,count})
- const actionCartDelete = (good) => ({type: 'CART_DELETE',good})
- const actionCartClean = () => ({type:'CART_CLEAN'})
- /* let store = createStore(authReducer); */
- /* const store = createStore(promiseReducer); */
- const store = createStore(combineReducers({promise: promiseReducer, auth: authReducer,cart: cartReducer}))
- /* store.subscribe(() => console.log(store.getState()));
- store.dispatch(actionCartAdd({_id:'pivas',name:'cherniga',price:50}));
- store.dispatch(actionCartAdd({_id: 'пиво', name: 'одеколонь', price: 30}))
- store.dispatch(actionCartAdd({_id: 'пиво', name: 'одеколонь', price: 30},5))
- store.dispatch(actionCartChange({_id: 'чипсы', name: 'одеколонь', price: 30}, 2))
- store.dispatch(actionCartAdd({_id:'чипсы', name: 'одеколонь', price: 30}))
- store.dispatch(actionCartChange({_id: 'pivas', name: 'cherniga', price: 50}, 1))
- store.dispatch(actionCartDelete({_id:'pivas',name:'cherniga'})); */
- const actionPromise = (name,promise) =>
- async dispatch => {
- dispatch(actionPending(name))
- try{
- let payload = await promise
- dispatch(actionFulfiled(name,payload))
- return payload
- }
- catch(e){
- dispatch(actionrRejected(name,e))
- }
- }
- const actionAuthLogin = (tokennn) => ({type:'AUTH_LOGIN',token:tokennn})
- const actionRootCats = () =>
- actionPromise('rootCats', gql(`query {
- CategoryFind(query: "[{\\"parent\\":null}]"){
- _id name
- }
- }`))
-
- const actionCatById = (_id) => //добавить подкатегории
- actionPromise('catById', gql(`query catById($q: String){
- CategoryFindOne(query: $q){
- _id name goods {
- _id name price images {
- url
- }
- }
- }
- }`, {q: JSON.stringify([{_id}])}))
- const actionGoodById = (_id) =>
- actionPromise('goodById', gql(`query goodById ($goodId: String){
- GoodFindOne(query:$goodId){
- _id name price images{
- url
- }
- description
- }
- }`,{goodId: JSON.stringify([{_id}])}))
- const actionFullRegister = (Login,password) =>
- actionPromise('fullRegister', gql(`mutation register($Login:String,$password:String){
- UserUpsert(user:{login:$Login,password:$password}){
- _id login
- }
- }`,{Login: Login, password: password}))
- const actionFullLogin = (Login,password) => async (dispatch) => {
- const tokennn = await dispatch(
- actionPromise('fullLogin', gql(`query login($Login:String,$password:String){
- login(login:$Login,password:$password)
- }`,{Login:Login,password:password}))
- );
- await dispatch(actionAuthLogin(tokennn));
- }
- const actionAllOrders = () =>
- actionPromise('allOrders',gql(`query orders{
- OrderFind(query:"[{}]"){
- _id total
- orderGoods{
- count total good{name,price,
- images{
- url
- }}
- }
- }
- }`))
- const actionCreateOrder = () => async (dispatch) =>{
- let orderGoods = [];
- Object.entries(store.getState().cart).map(([_id,{count}])=>orderGoods.push({"count":count,"good":{_id:_id}}))
- actionPromise('createOrder',gql(`mutation newOrder($order:OrderInput){
- OrderUpsert(order:$order){
- _id total
- }
- }`,{order:{orderGoods}}));
- await store.dispatch(actionCartClean());
- }
- const actionSearchGood = (good) =>
- actionPromise('searchGood', gql(`query gf($query: String){
- GoodFind(query: $query){
- _id, name, description, price, images{
- _id, url
- }
- }
- }`, {query: JSON.stringify([
- {
- $or: [{name: `/${good}/`}, {description: `/${good}/`}] //регулярки пишутся в строках
- },
- {
- sort: [{name: 1}]} //сортируем по title алфавитно
- ])
- }))
- store.dispatch(actionRootCats())
-
- store.subscribe(() => {
- const {promise:{rootCats}} = store.getState()
- if (rootCats?.payload){
- aside.innerHTML = ''
- for (const {_id, name} of rootCats?.payload){
- const link = document.createElement('a')
- link.href = `#/category/${_id}`
- link.innerText = name
- aside.append(link)
- }
- }
- })
- window.onhashchange = () => {
- const [, route, _id] = location.hash.split('/')
-
- const routes = {
- category(){
- store.dispatch(actionCatById(_id))
- },
- good(){ //задиспатчить actionGoodById
- store.dispatch(actionGoodById(_id));
-
- },
- login(){
- //отрисовка тут
- /* store.subscribe(() => { */
- const [,route,id] = location.hash.split('/')
- if(route === 'login'){
- main.innerHTML = `<h1>Login</h1>`
- let loginForm = document.createElement('div');
- loginForm.innerHTML = `<label>login <input id="login"></label>
- <label>password <input id="password"></label>
- <button id="logButton">Login</button>`
- main.append(loginForm);
- logButton.addEventListener('click', function Login(){
- console.log(login.value, password.value);
- store.dispatch(actionFullLogin(login.value, password.value))
- store.getState();
- /* store.dispatch(actionAuthLogin(store.getState().promise.fullLogin.payload))
- store.getState(); */
- })
- }
-
- /* }) */
- //по кнопке - store.dispatch(actionFullLogin(login, password))
- },
- register(){
- const [,route,id] = location.hash.split('/');
- if(route === 'register'){
- main.innerHTML = `<h1>Register</h1>`
- let registerForm = document.createElement('div');
- /* registerForm.innerHTML = `<label>login <input id="login"></label>
- <label>password <input id="password" type="paasword"></label>
- <button id="registerButton">Register</button>` */
- let labelLog = document.createElement('label');
- labelLog.innerText = 'login';
- let login = document.createElement('input');
- labelLog.append(login);
- let labelPswd = document.createElement('label');
- labelPswd.innerText = 'Password';
- let password = document.createElement('input');
- password.type = 'password';
- labelPswd.append(password);
- let registerButton = document.createElement('button');
- registerButton.innerText = 'Register';
- registerForm.append(labelLog);
- registerForm.append(labelPswd);
- registerForm.append(registerButton);
- main.append(registerForm);
- registerButton.addEventListener('click', function register(){
- console.log(login.value, password.value);
- store.dispatch(actionFullRegister(login.value, password.value))
- })
- }
- //отрисовка тут
- //по кнопке - store.dispatch(actionFullRegister(login, password))
- },
- dashboard(){
- store.dispatch(actionAllOrders());
- },
- cart(){
- const[,route,id] = location.hash.split('/')
- const cart = store.getState().cart;
- if(route === 'cart'){
- main.innerHTML = `<h1>Cart</h1>`
- for(let good in cart){
- /* goods.innerHTML = `<img src="${backendURL}/${cart[good].good.images[0].url}">
- <p>${cart[good].good.name}</p>
- <input type="number" value=${cart[good].count} min="0" id="count">
- <button id="plusCount">+</button> <button id="minusCount">-</button>
-
- ` */
- let goods = document.createElement('div');
- let img = document.createElement('img');
- img.src = `${backendURL}/${cart[good].good.images[0].url}`;
- let name = document.createElement('p');
- name.innerText = `${cart[good].good.name}`
- let count = document.createElement('input');
- count.type = 'number';
- count.min = 1;
- count.value = cart[good].count;
- let countPlus = document.createElement('button');
- countPlus.innerText = '+'
- let countMinus = document.createElement('button');
- countMinus.innerText = '-';
- countPlus.onclick = () => {
- cart[good].count++;
- count.value = cart[good].count;
- store.dispatch(actionCartChange(cart[good].good, +count.value))
- }
- countMinus.onclick = () =>{
- cart[good].count--;
- count.value = cart[good].count;
- if(cart[good].count < 1){
- count.value = 1;
- cart[good].count = 1;
- store.dispatch(actionCartChange(cart[good].good, +count.value))
- }
- store.dispatch(actionCartChange(cart[good].good, +count.value))
- }
- count.oninput = () => {
- store.dispatch(actionCartChange(cart[good].good, +count.value))
- }
- let removeBtn = document.createElement('button');
- removeBtn.innerText = 'Remove';
- removeBtn.onclick = () => {
- store.dispatch(actionCartDelete(cart[good].good))
- window.onhashchange()
- cartIcon.innerHTML = `Cart ${cart[good].count}`
- }
- goods.append(img);
- goods.append(name);
- goods.append(count);
- goods.append(countPlus);
- goods.append(countMinus);
- goods.append(removeBtn);
- main.append(goods);
-
- }
- let orderButton = document.createElement('button');
- orderButton.innerText = 'Order';
- orderButton.onclick = () => {
- store.dispatch(actionCreateOrder());
- window.onhashchange()
- cartIcon.innerHTML = `Cart`
- }
- if(localStorage.authToken && Object.keys(cart).length !== 0){
- orderButton.disabled = ""
- } else {
- orderButton.disabled = "true"
- }
- main.append(orderButton);
- }
-
- }
- }
- if (route in routes)
- routes[route]()
- }
- window.onhashchange()
- store.subscribe(() => {
- const {promise: {catById}} = store.getState();
- const [,route,_id] = location.hash.split('/');
- if(catById?.payload && route === 'category'){
- const {name} = catById.payload;
- main.innerHTML = `<h1>${name}</h1> TYT PODCATEGORII`;
- for(const {_id,name,price,images} of catById.payload.goods){
- const card = document.createElement('div')
- /* card.innerHTML = `<h2>${name}</h2>
- <img src="${backendURL}/${images[0].url}">
- <strong>${price}UAH</strong>
- <a href="#/good/${_id}">ссылка на товарчик</a>
- <button id="buyGood">Купить</button>
-
- ` */
- let named = document.createElement('h2');
- named.innerText = `${name}`;
- let imaged = document.createElement('img');
- imaged.src = `${backendURL}/${images[0].url}`;
- let priced = document.createElement('strong');
- priced.innerText = `${price}`;
- let link = document.createElement('a');
- link.href = `#/good/${_id}`;
- link.innerText = 'ссылка на товарчик';
- let buttonBuy = document.createElement('button');
- buttonBuy.innerText = 'Купить';
- buttonBuy.onclick = () => {
- store.dispatch(actionGoodById(_id));
- store.dispatch(actionCartAdd({_id,name,price,images}));
- }
- card.append(named);
- card.append(imaged);
- card.append(priced);
- card.append(link);
- card.append(buttonBuy);
- main.append(card);
- }
- }
- })
- store.subscribe(() => {
- const {promise: {goodById}} = store.getState();
- const [,route,id] = location.hash.split('/')
- if(goodById?.payload && route === 'good'){
- const {name,price,description,images} = goodById.payload;
- main.innerHTML = `<h1>${name}</h1>`
- const card = document.createElement('div');
- card.innerHTML = `<h2>${name}</h2>
- <img src="${backendURL}/${images[0].url}">
- <p>${description}</p>
- <strong>${price}UAH</strong>
- <button id="buyGood">Купить</button>
- `
- main.append(card);
- let buyGood = document.getElementById('buyGood');
- buyGood.addEventListener('click', function addToCart(){
- console.log(id);
- store.dispatch(actionCartAdd(store.getState().promise.goodById.payload));
- })
- }
- })
- store.subscribe(() => {
- let counts = 0;
- const cartIcon = document.getElementById('cartIcon');
- const orders = store.getState().cart;
- for (let order in orders){
- counts += orders[order].count
- cartIcon.innerHTML = `<a href="#/cart">Cart ${counts}</a>`
- /* if(!orders[order].count){
- cartIcon.innerHTML = `Cart ${counts}`
- } */
- }
- })
- store.subscribe(async() => {
- const[,route,id] = location.hash.split('/')
- const {promise: {allOrders}} = await store.getState();
- if(route === 'dashboard' && allOrders.payload){
- main.innerHTML = `<h1>Dashboard</h1>`
- for(const{_id,total,orderGoods} of allOrders.payload){
- let order = document.createElement('div');
- let idOfOrder = document.createElement('h2');
- idOfOrder.innerText = `${_id}`;
- let totalCost = document.createElement('label');
- totalCost.innerText = `${total}`
- order.append(idOfOrder);
- order.append(totalCost);
- for(const{count,total,good} of orderGoods){
- let card = document.createElement('div');
- card.innerHTML = `<h2 id="name">${good.name}</h2>
- <p id="counted">${count}</p>
- <p id="totaled">${total}</p>
- <img src="${backendURL}/${good.images[0].url}">
- `
- order.append(card);
- }
-
-
- main.append(order);
- }
- }
- })
- let inputSearch = document.createElement('input');
- inputSearch.type = "text";
- let header = document.getElementById('header');
- header.append(inputSearch);
- let divWithGood = document.createElement('div');
- divWithGood.style.display = 'none';
- header.append(divWithGood);
- function render(parent,data){
- console.log(data);
- }
- store.subscribe(() => {
- let re = /\s* \s*/;
- inputSearch.oninput = () => {
- let newStr = inputSearch.value.trim().split(re).join("|");
- store.dispatch(actionSearchGood(newStr));
- }
- inputSearch.onfocus = () => {
- divWithGood.style.display = 'block';
- const searchGood = store.getState().promise.searchGood;
- render(divWithGood,searchGood);
- }
- inputSearch.blur = () => {
- divWithGood.style.display = 'none';
- render(divWithGood,searchGood);
- }
- })
- let token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2MWJiNjNjOWM3NTBjMTJiYTZiYTRiMzgiLCJsb2dpbiI6IkFub24iLCJhY2wiOlsiNjFiYjYzYzljNzUwYzEyYmE2YmE0YjM4IiwidXNlciJdfSwiaWF0IjoxNjQwMjAwNTU2fQ.P_JXFko7OFObxVn8uB6TR3R1V9aB1MMQrgX58MpEq5E';
- /* store.dispatch(actionPromise('delay1000', delay(1000)))
- store.dispatch(actionPromise('delay2000', delay(2000))) */
-
- // store.dispatch(actionAuthLogin(token))
- const actionAuthLogout= () => ({type: 'AUTH_LOGOUT'})
- // store.dispatch(actionAuthLogout());
- /* console.log(store.getState()); */
- /* const actionRegister = (login,password) =>
- actionPromise('register', gql(`mutation register($Login:String,$password:String){
- UserUpsert(user:{login:$Login,password:$password}){
- _id login
- }
- }`,{login:login,password:password}));
- store.dispatch(actionRegister('aufff', '123456')); */
-
-
- /* const combinedStore = createStore(combineReducers({promise: promiseReducer, auth: authReducer})) */
- //search
- // let re = /\s* \s*/;
- // let input = document.createElement('input');
- // input.type = 'text';
- // document.body.append(input);
- // input.oninput = () => {
- // let newStr = input.value.trim().split(re).join("|");
- // console.log(`/${newStr}/`);
- // }
|