Постановка задачи и обзор методов ее решения
Содержание
Введение. 3
1. Описание предметной области. 5
2. Постановка задачи и обзор методов ее решения. 6
3. Обоснование инструментов разработки. 7
4. Реализация. 13
4.1 Логическая структура Web-приложения. 13
4.2 Физическая структура Web-приложения. 14
4.3 Описание структуры и формата страниц. 18
4.4 Описание ограничений доступа к данным.. 23
4.5 Описание используемых библиотек и элементов управления. 25
4.6 Описание используемых функций и процедур. 26
5. Тестирование. 27
6. Применение. 30
6.1 Назначение и область применения Web-приложения. 30
6.2 Описание организации диалога с пользователем.. 30
6.3 Программно-аппаратное обеспечение сервера и клиента. 32
6.4 Руководство пользователя. 33
Заключение. 40
Список литературы.. 41
Приложение. 42
Введение
Успех любого бизнеса во многом зависит от того, насколько эффективно компания доводит свою информацию до клиентов и партнеров.
Создание интернет-сайта и размещение его в Интернете - один из альтернативных методов позиционирования компании и информирования целевой аудитории.
Именно в Интернете многие ищут подробную, и свежую информацию, на основе которой можно получить представление об интересующей компании, товарах и услугах.
Сейчас трудно представить крупную компанию без интернет-сайта. Наличие у компании хорошего сетевого представительства не только усиливает положительный образ фирмы, но и говорит в пользу надежности и основательности компании, создает определенный имидж и впечатление.
В настоящее время наиболее популярным видом виртуальной торговли является интернет-магазин. Интернет-магазин обычно содержит наглядный и красочный каталог предоставляемых товаров, с их достаточным описанием и указанием цены, что позволяет заинтересовать потенциального покупателя, помочь ему сделать выбор и, в итоге, совершить покупку.
Преимущества интернет-магазина:
- не требует затрат на аренду площади, найма продавцов и другого персонала;
- доступ к виртуальным витринам магазина может получить любой покупатель, не зависимо от места проживания;
- интернет-магазин не имеет ограничений на виртуальную площадь;
- владелец интернет-магазина может сдавать в аренду свои виртуальные торговые площади так же, как и владелец обычного магазина;
- срок и стоимость создания интернет-магазина несоизмеримо ниже, чем обычного магазина;
- потенциальный покупатель получает исчерпывающую информацию об интересующем его товаре или услуге без помощи посредников (продавца, менеджера);
- интернет-магазин, работающий в режиме on-line, предполагает обратную связь с покупателем (форумы, чаты, гостевые книги), что позволяет оперативно ответить на вопросы пользователей, провести маркетинговые исследования, получить отзывы и пожелания;
- можно разместить сколь угодно много товаров или описать любое количество услуг;
- возможность делать покупки, не выходя из дома, делают интернет-магазины еще более привлекательными для покупателей.
Делая свой выбор в пользу открытия интернет-магазина, компания переходит на более высокий уровень развития своего бизнеса и делает свой ассортимент более доступным для широкого круга покупателей.
В ходе выполнения данного курсового проекта необходимо разработать сайт интернет-магазина готовой продукции с системой расчета стоимости перевозки продукции со склада. В нем должен быть необходимый перечень товара, а также интуитивно понятный пользователю интерфейс.
Описание предметной области
Интернет-магазин - это привычный каждому пользователю интернета web-сайт, представляющий информацию о товарах в удобном структурированном виде.
Интернет-магазины создаются с применением систем управления содержимым сайтов, оснащенных необходимыми модулями. Крупные интернет-магазины работают на специально разработанных или адаптированных типовых системах управления.
Система управления содержимым сайта интернет-магазина может быть коробочным товаром, самостоятельно устанавливаемым на хостинг-площадку, может быть частной разработкой web-студии, ей же обслуживаемой, или может быть программным сервисом, предоставляемым с помесячной оплатой.
С технической точки зрения интернет-магазин - это совокупность web-витрины и торговой системы - фронт-системы и бэк-офиса. Web-витрина предоставляет интерфейс к базе данных продаваемых товаров (в виде каталога, прайс-листа), работает с виртуальной торговой тележкой, оформляет заказы и регистрирует покупателя, предоставляет помощь покупателю в онлайновом режиме, передает информацию в торговую систему и обеспечивает безопасность личной информации покупателя. Далее торговая система осуществляет автоматическую обработку поступающих заказов - резервирует товар на складе, контролирует оплату и доставку товара.
В общем случае основные функции интернет-магазина - это информационное обслуживание покупателя, обработка заказов, проведение платежей, а также сбор и анализ различной статистической информации. Как было упомянуто выше, программный комплекс управления интернет-магазином позволяет формировать и интерфейс с покупателем, и функциональные возможности интернет-магазина, исходя из потребностей компании.
Реализация
Тестирование
Совместимость сайта с различными браузерами и разными настройками браузеров производилось на последних версиях браузера, в соответствии с таблицей 5.1.
Таблица 5.1 – совместимость с браузерами.
Браузер | Оценка |
Google Chrome | Положительная. Все эффекты работают отлично. |
Mozilla Firefox | Положительная. Все эффекты работают отлично. |
Opera | Положительная. Все эффекты работают отлично. |
Windows Internet Explorer | Нежелательно. Некоторые эффекты не работают. |
Для правильности работы сайта, рекомендуется использовать Google Chrome версию 31 и выше.
При вводе в адресную строку не существующий адрес страницы пользователя автоматически перенаправит на главную страницу сайта.
При регистрации на сайте необходимо заполнить все поля, если поля будут не заполнены отобразится ошибка, в соответствии с рисунком 5.2.
Рисунок 5.2 – Ошибка незаполненного поля при регистрации.
Данная валидация производится с помощью html5 возможностей, в частности с помощью атрибута «required». В случае, если два введенных при регистрации пароля не совпадают отобразится ошибка, в соответствии с рисунком 5.3.
Рисунок 5.3 – Ошибка несовпадающих паролей при регистрации.
Если введенный логин уже зарегистрирован отобразится ошибка, в соответствии с рисунком 5.4
Рисунок 5.4 – Ошибка занятого логина при регистрации.
Если при авторизации пользователь введет неправильный пароль отобразится ошибка, в соответствии с рисунком 5.5
Рисунок 5.5 – Ошибка неверного пароля при авторизации.
При успешной регистрации или авторизации, пользователь будет перенаправлен на страницу «Каталог». Для корректного функционирования сайта в браузере должна быть включена поддержка использования сценариев JavaScript.
Применение
Руководство пользователя
Для работы с Web-приложением необходим доступ к сети интернет.
Для работы с интернет-магазином необходимо ввести в адресную строку адрес моего интернет-магазина и нажать на Enter. После этого загрузится главная страница сайта в соответствии с рисунком 6.4.1.
Рисунок 6.4.1 – Главная страница.
Для регистрации необходимо нажать на кнопку «Авторизация». После этого откроется страница «Авторизация» соответствии с рисунком 6.4.2.
Рисунок 6.4.2 – страница «Авторизация».
На этой странице необходимо нажать кнопку «Регистрация», появится форма для регистрации, в которой необходимо заполнить все поля и нажать кнопку «Зарегистрироваться». Все поля являются обязательными для заполнения. Если поля оставить не заполненными, то отобразится ошибка в соответствии с рисунком 6.4.3.
Рисунок 6.4.3 – Сообщение об ошибке.
Если введенный логин совпадет с уже зарегистрировавшимся пользователем, то на экране отобразится сообщение об ошибке в соответствии с рисунком 6.4.4.
Рисунок 6.4.4 – Сообщение об ошибке.
После правильного ввода всех необходимых данных откроется страница «Каталог» в соответствии с рисунком 6.4.5.
Рисунок 6.4.5 – страница «Каталог».
Для того что бы заказать товар необходимо выбрать категорию. Откроется страница со списком товаров в категории, в соответствии с рисунком 6.4.6.
Рисунок 6.4.6 – Страница категории «Товары для котов».
На этой странице под необходимым товаром в поле необходимо указать нужное число единиц товара и нажать кнопку «Добавить в корзину». Затем с помощью главного меню перейти на страницу «Корзина», в соответствии с рисунком 6.4.7.
Рисунок 6.4.7 – Страница «Корзина».
На этой странице необходимо выбирать ваш регион и ввести адрес. В зависимости от стоимости заказа и выбранного региона будет выведена информация о стоимости доставки товаров. Если пользователя все устраивает необходимо нажать на кнопку «Подтвердить заказ».
Заключение
В процессе проектирования курсового проекта был разработан интернет-магазин по продажам товаров для домашних животных.
Интернет-магазин предназначен для продажи различных товаров через интернет. Областью применения данного Web-приложения выступает интернет-торговля.
Создание данного интернет-магазина позволит продвигать и продавать товары, уменьшить издержки на рекламу и приобрести дополнительный рынок сбыта своего товара, расширить клиентскую аудиторию и, как следствие, увеличение прибыли.
Интернет-магазин имеет удобный и понятный интерфейс, благодаря которому не требуется излишних усилий в освоении работы с сайтом. Вся информация не содержит ничего лишнего.
Результаты проверки показали, что система работает без ошибок, имеется возможность работы с веб-сайтом во всех популярных браузерах.
В результате разработки курсового проекта были отточены навыки в дизайне сайтов, проектировки интерфейсов, разработке логотипов. Приобретены практические умения JavaScript, HTML и CSS верстки сайтов.
Список литературы
1. Node.js Разработка серверных веб-приложений на JavaScript/ Дэвид Хэррон Изд-во: ДМК Пресс, 2012 – 146 с.
2. Изучаем JavaScript // Майкл Моррисон — СПб.: Питер, 2012. — С.608
3. Титтел Эд, Бурмейстер Мэри. HTML 4 для "чайников". 6-е издание. М.: Из-дательский дом “Диалектика -Вильямс” – 2009. - 368с.
4. Веб-приложения на JavaScript. Год: 2012. // Маккоу — СПб.: Питер, 2012. — С.560 608.
5. Большая книга CSS3. // Дэвид Макфарланд. — СПб.: Питер, 2014. — С. 608.
6. HTML5 и CSS3. Веб-разработка по стандартам нового поколения // Брайан Хоган — СПб.: Питер, 2014. — С. 272.
7. Лебедев А. Руководство Лебедев А. – Москва.: Издательство Студии Артемия Лебедева, 2011. – 452 с.
8. Спейнауэр С. Справочник Web-мастера. СПб.: BHV, 1997. – 368 с.
9. Ратшиллер Т., Геркен Т. PHP4: разработка Web-приложений. - СПб: Питер, 2001. - 384 с.
10. Томсон Л., Веллинг Л. Разработка Web-приложений на PHP и MySQL. - К.: "ДиаСофт", 2001. - 672 с
11. Яргер Р., Риз Дж., Кинг Т. MySQL и mSQL. Базы данных для небольших предприятий и Интернета. - СПб: Символ-Плюс, 2000 - 560 с.
12. Орлов С.Д. Технологии разработки программного обеспечения. Учеб. пособие. 2-е изд. СПб.: Питер, 2003. – 480 с.
Приложение
Листинг файла package.json
{"dependencies": {
"async": "^2.4.1",
"body-parser": "^1.17.2",
"connect-mongo": "^1.3.2",
"cookie-parser": "^1.4.3",
"express": "^4.15.3",
"express-session": "^1.15.3",
"mongoose": "^4.10.3",
"serve-favicon": "^2.4.3"
}
}
Листинг файла config.js
module.exports = {port: 49002,
mongodb: {
"main": "mongodb://127.0.0.1:27017/main"
},
session: "aXVmN7y{Xw5|9zN%El2m"
};
Листинг файла createDB.js
varmongoose = require('./lib/mongoose');varasync = require('async');
async.series([
open,
dropDatabase,
requireModels,
createUsers,
createCategory,
createGoods
], function(err) {
console.log(arguments);
});
functionopen(callback) {
mongoose.connection.on('open', callback);
}
functiondropDatabase(callback) {
vardb = mongoose.connection.db;
db.dropDatabase(callback);
}
functionrequireModels(callback) {
require('./models/user');
require('./models/category');
require('./models/goods');
async.each(Object.keys(mongoose.models), function(modelName, callback) {
mongoose.models[modelName].ensureIndexes(callback);
}, callback);
}
functioncreateUsers(callback) {
varusers = [
{username: 'Вася', password: 'supervasya'},
{username: 'Петя', password: '123'},
{username: 'admin', password: 'thetruehero'}
];
async.each(users, function(userData, callback) {
varuser = newmongoose.models.User(userData);
user.save(callback);
}, callback);
}
functioncreateCategory(callback) {
varcategories = [
{id: 0, name: 'Товары для собак', img: 'dogs.jpg'},
{id: 1, name: 'Товары для котов', img: 'cats.jpg'}
];
async.each(categories, function(categoryData, callback) {
varcategory = newmongoose.models.Category(categoryData);
category.save(callback);
}, callback);
}
functioncreateGoods(callback) {
vargoods = [
{id: 0, category: 0, price: 10, name: 'Корм для собак Чаппи', img: 'dogs1.jpg'},
{id: 1, category: 0, price: 20, name: 'Корм для собак Trainer Natural Mini Adult', img: 'dogs2.jpg'},
{id: 2, category: 1, price: 30, name: 'Корм Brit Care Crazy для котят', img: 'cats1.jpg'},
{id: 3, category: 0, price: 40, name: 'Корм для собак Acana PACIFICA DOG', img: 'dogs3.jpg'},
{id: 4, category: 1, price: 50, name: 'Корм для кошек Gourmet Кусочки в соусе', img: 'cats2.jpg'},
{id: 5, category: 1, price: 60, name: 'Консервированный корм для кошек Friskies', img: 'cats3.jpg'},
];
async.each(goods, function(goodsData, callback) {
vargood = newmongoose.models.Goods(goodsData);
good.save(callback);
}, callback);
}
Листинг файла error.js
varutil = require('util');varhttp = require('http');
// ошибки для выдачи посетителю
functionHttpError(status, message) {
Error.apply(this, arguments);
Error.captureStackTrace(this, HttpError);
this.status= status;
this.message= message || http.STATUS_CODES[status] || "Error";
}
util.inherits(HttpError, Error);
HttpError.prototype.name= 'HttpError';
exports.HttpError = HttpError;
Листинг файла index.js
'use strict';consthttp = require('http'),
express = require('express'),
cookieParser = require('cookie-parser'),
bodyParser = require('body-parser'),
favicon = require('serve-favicon'),
config= require('./config'),
path = require('path');
varapp = express(), port, server;
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(cookieParser());
app.use(bodyParser.urlencoded({limit: '<100mb>'}));
app.use(require('./middleware/session'));
app.use(require('./middleware/sendHttpError'));
app.use(require('./middleware/loadUser'));
port = config.port|| 49001;
app.set('port', port);
server = http.createServer(app);
server.on('error', serverError);
server.on('listening', serverListening);
require('./routes')(app);
app.use(express.static(path.join(__dirname, 'public')));
server.listen(port);
require('./createDB');
functionserverError(error) {
if(error.syscall!== 'listen') {
throwerror;
}
varbind = typeofport === 'string'? 'Pipe '+ port : 'Port '+ port;
if(error.code === 'EACCES') {
console.error(bind + ' requires elevated privileges');
process.exit(1);
} else if(error.code === 'EADDRINUSE') {
console.error(bind + ' is already in use');
process.exit(1);
} else{
throwerror;
}
}
functionserverListening() {
varaddress = server.address(),
bind = typeofaddress === 'string'? 'pipe '+ address : 'port '+ address.port;
console.log('Listening on '+ bind);
}
Листинг файла routes.js
varpath = require('path'),checkAuth = require('./middleware/checkAuth');
module.exports = function(app) {
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/public/template/index.html'));
});
app.post('/register', require('./routes/register').post);
app.post('/login', require('./routes/login').post);
app.get('/login', checkAuth, require('./routes/login').get);
app.post('/logout', require('./routes/logout').post);
app.get('/categories', checkAuth, require('./routes/categories').get);
app.post('/goods', checkAuth, require('./routes/goods').post);
};
Листинг файла lib/mongoose.js
varmongoose = require('mongoose');var config= require('../config');
mongoose.connect(config.mongodb.main);
module.exports = mongoose;
Листинг файла lib/session_store.js
constsession = require('express-session');constMongoStore = require('connect-mongo')(session);
module.exports = function(mongoose) {
return newMongoStore({ mongooseConnection: mongoose.connection})
};
Листинг файла middleware/checkAuth.js
module.exports = function(req, res, next) {if(!req.session.user) {
returnres.status(401).send({ error: "Вы не авторизованы"});
}
next();
};
Листинг файла middleware/loadUser.js
varUser = require('../models/user').User;module.exports = function(req, res, next) {
req.user = res.locals.user = null;
if(!req.session.user) returnnext();
User.findById(req.session.user, function(err, user) {
if(err) returnnext(err);
req.user = res.locals.user = user;
next();
});
};
Листинг файла middleware/sendHttpError.js
module.exports = function(req, res, next) {res.sendHttpError = function(error) {
res.status(error.status);
if(res.req.headers['x-requested-with'] == 'XMLHttpRequest') {
res.json(error);
} else{
res.send(error.message);
}
};
next();
};
Листинг файла middleware/session.js
varsession = require('express-session'),config= require('../config'),
mongoose = require('../lib/mongoose'),
sessionStore = require('../lib/session_store')(mongoose);
module.exports = session({
secret: config.session,
name: 'sid',
resave: false,
saveUninitialized: false,
cookie: {
maxAge: null
},
store: sessionStore
});
Листинг файла models/category.js
varutil = require('util');varmongoose = require('../lib/mongoose'),
Schema = mongoose.Schema;
varschema = newSchema({
id: {
type: Number,
required: true
},
name: {
type: String,
required: true
},
img: {
type: String,
required: true
}
});
exports.Category= mongoose.model('Category', schema);
Листинг файла models/goods.js
varutil = require('util');varmongoose = require('../lib/mongoose'),
Schema = mongoose.Schema;
varschema = newSchema({
id: {
type: Number,
required: true
},
name: {
type: String,
required: true
},
img: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
category: {
type: Number,
required: true
},
quantity: {
type: Number,
required: true,
default: 0
}
});
exports.Goods= mongoose.model('Goods', schema);
Листинг файла models/user.js
varcrypto = require('crypto');varasync = require('async');
varutil = require('util');
varmongoose = require('../lib/mongoose'),
Schema = mongoose.Schema;
varschema = newSchema({
username: {
type: String,
unique: true,
required: true
},
hashedPassword: {
type: String,
required: true
},
salt: {
type: String,
required: true
},
created: {
type: Date,
default: Date.now
}
});
schema.methods.encryptPassword = function(password) {
returncrypto.createHmac('sha1', this.salt).update(password).digest('hex');
};
schema.virtual('password')
.set(function(password) {
this._plainPassword= password;
this.salt= Math.random() + '';
this.hashedPassword= this.encryptPassword(password);
})
.get(function() {
return this._plainPassword;
});
schema.methods.checkPassword = function(password) {
return this.encryptPassword(password) === this.hashedPassword;
};
schema.statics.authorize = function(username, password, callback) {
varUser = this;
async.waterfall([
function(callback) {
User.findOne({username: username}, callback);
},
function(user, callback) {
if(user) {
if(user.checkPassword(password)) {
callback(null, user);
} else{
callback(newAuthError("Неправильный пароль"));
}
} else{
callback(newAuthError("Пользователь с таким логином не зарегистрирован"));
}
}
], callback);
};
schema.statics.register = function(username, password, repeat, callback) {
varUser = this;
async.waterfall([
function(callback) {
User.findOne({username: username}, callback);
},
function(user, callback) {
if(user) {
callback(newAuthError("Такой пользователь уже зарегистрирован"));
} else{
if(password === repeat) {
varuser = newUser({username: username, password: password});
user.save(function(err) {
if(err) returncallback(err);
callback(null, user);
});
} else{
callback(newAuthError("Пароли не совпадают"));
}
}
}
], callback);
};
exports.User= mongoose.model('User', schema);
functionAuthError(message) {
Error.apply(this, arguments);
Error.captureStackTrace(this, AuthError);
this.message= message;
}
util.inherits(AuthError, Error);
AuthError.prototype.name= 'AuthError';
exports.AuthError = AuthError;
Листинг файла public/app.js
'use strict';angular
.module('myApp', ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider.state('home', {
url: '/home',
templateUrl: 'template/home.html',
pageTitle: 'Главная',
params: {}
}).state('chat', {
url: '/chat',
templateUrl: 'template/chat.html',
pageTitle: 'Чат',
params: {}
}).state('login', {
url: '/login',
templateUrl: 'template/login.html',
pageTitle: 'Вход',
params: {}
}).state('logout', {
url: '/logout',
pageTitle: 'Выход',
params: {},
controller: function($http, $state) {
$http({method: 'POST', url: '/logout'});
$state.go('home');
window.location.reload();
}
}).state('categories', {
url: '/categories',
templateUrl: 'template/categories.html',
pageTitle: 'Каталог',
params: {},
resolve:{
access: function($http){
return$http({method: 'GET', url: '/login'}).then(function(res) {
returnres;
}, function(res) {
returnres;
});
},
}
}).state('goods', {
url: '/goods',
templateUrl: 'template/goods.html',
pageTitle: 'Товары',
params: {
category: null
},
resolve:{
access: function($http){
return$http({method: 'GET', url: '/login'}).then(function(res) {
returnres;
}, function(res) {
returnres;
});
},
}
}).state('cart', {
url: '/cart',
templateUrl: 'template/cart.html',
pageTitle: 'Корзина',
params: {
category: null
},
resolve:{
access: function($http){
return$http({method: 'GET', url: '/login'}).then(function(res) {
returnres;
}, function(res) {
returnres;
});
},
}
}).state('about', {
url: '/about',
templateUrl: 'template/about.html',
pageTitle: 'О нас',
params: {}
}).state('shipping', {
url: '/shipping',
templateUrl: 'template/shipping.html',
pageTitle: 'Доставка',
params: {}
}).state('profile', {
url: '/profile',
templateUrl: 'template/profile.html',
pageTitle: 'Личный кабинет',
params: {}
});
$urlRouterProvider.otherwise('/home');
$stateProvider.state("otherwise", {url: '/otherwise'});
}])
.run(['$state', '$rootScope', '$stateParams', 'userService', '$http',
function($state, $rootScope, $stateParams, userService, $http) {
$rootScope.$state= $state;
$rootScope.$stateParams= $stateParams;
$rootScope.$on("$includeContentLoaded", function() {
$('body').scrollTop(0);
});
$rootScope.$on('$stateChangeSuccess', function() {
userService.navChange();
});
$http({
url: "/login",
method: "GET"
}).then(function(res) {
userService.username= res.data.username;
}, function(res) {
userService.username= false;
});
}])
.service('userService', function() {
return{
goods: null,
username: null,
order: {}
};
})
.controller('navController', function($state, userService, $http, $scope, $rootScope) {
varvm = this;
userService.navChange = function() {
vartabs = {
home: {name: 'Главная', url: 'home', active: false},
login: {name: 'Авторизация', url: 'login', active: false},
logout: {name: 'Выход', url: 'logout', active: false},
categories: {name: 'Каталог', url: 'categories', active: false},
cart: {name: 'Корзина', url: 'cart', active: false},
about: {name: 'О нас', url: 'about', active: false},
profile: {name: 'Личный кабинет', url: 'profile', active: false},
shipping: {name: 'Доставка', url: 'shipping', active: false}
};
if(tabs[$state.current.name]) {
tabs[$state.current.name].active= true;
} else{
tabs['categories'].active= true;
}
if(userService.username) {
vm.tabs= [tabs.home, tabs.about, tabs.shipping, tabs.categories, tabs.cart, tabs.profile, tabs.logout];
} else{
vm.tabs= [tabs.home, tabs.about, tabs.shipping, tabs.login];
}
}
})
.controller('homeController', function($state, $scope, $rootScope) {
varvm = this;
})
.controller('aboutController', function($state, $scope, $rootScope) {
varvm = this;
})
.controller('shippingController', function($state, $scope, $rootScope) {
varvm = this;
})
.controller('profileController', function($state, $scope, $rootScope) {
varvm = this;
})
.controller('loginController', function($state, $http, userService, $scope, $rootScope) {
varvm = this;
vm.loginRegister= true;
vm.registerForm = function() {
vm.loginRegister= false;
vm.error= false;
};
vm.loginForm = function() {
vm.loginRegister= true;
vm.error= false;
};
vm.register = function() {
if(vm.password=== vm.repeat) {
$http({
url: "/register",
method: "POST",
headers: {
"content-type": 'application/x-www-form-urlencoded'
},
data: 'username='+ vm.username+ '&password='+ vm.password+ '&repeat='+ vm.repeat
}).then(function(res) {
userService.username= vm.username;
userService.navChange();
$state.go('categories');
}, function(res) {
if(res.status === 403) {
vm.error= res.data.message;
} else{
$state.go('error');
}
});
} else{
vm.error= 'Введенные пароли не совпадают';
}
};
vm.login = function() {
$http({
url: "/login",
method: "POST",
headers: {
"content-type": 'application/x-www-form-urlencoded'
},
data: 'username='+ vm.username+ '&password='+ vm.password
}).then(function(res) {
userService.username= vm.username;
userService.navChange();
$state.go('categories');
}, function(res) {
if(res.status === 403) {
vm.error= res.data.message;
} else{
$state.go('error');
}
});
}
})
.controller('categoriesController', function($state, $http, $scope, $rootScope) {
varvm = this;
$state.current.resolve.access($http).then(function(res){
if(res.status === 401) {
vm.error= res.data.error;
}
});
$http({
url: "/categories",
method: "GET"
}).then(function(res) {
vm.categories= res.data;
}, function(res) {
vm.error= res.data.error;
});
vm.openCategory = function(id) {
$state.go('goods', { category: id })
};
})
.controller('goodsController', function($state, $http, $scope, $rootScope, $stateParams, userService) {
varvm = this;
$state.current.resolve.access($http).then(function(res){
if(res.status === 401) {
vm.error= res.data.error;
}
});
$http({
url: "/goods",
method: "POST",
headers: {
"content-type": 'application/x-www-form-urlencoded'
},
data: 'category='+ $stateParams.category
}).then(function(res) {
vargood, i;
vm.goods= res.data;
for(good inuserService.order) {
for(i = 0; i < vm.goods.length; i++) {
if(vm.goods[i].id == good) {
vm.goods[i].quantity= userService.order[good];
}
}
}
}, function(res) {
$state.go('home');
});
vm.addToCart = function(id, price, quantity) {
userService.order[id] = quantity;
}
})
.controller('cartController', function($state, $http, $scope, $rootScope, $stateParams, userService) {
varvm = this;
vm.all= 0;
vm.state= 0;
vm.locations= [{name:'Минск'},{name:'Минская область'},{name:'Беларусь'}];
$state.current.resolve.access($http).then(function(res){
if(res.status === 401) {
vm.error= res.data.error;
}
});
$http({
url: "/goods",
method: "POST"
}).then(function(res) {
vargood, i;
vm.goods= res.data;
vm.shipping= 0;
for(good inuserService.order) {
for(i = 0; i < vm.goods.length; i++) {
if(vm.goods[i].id == good) {
vm.goods[i].quantity= userService.order[good];
}
}
}
for(i = 0; i < vm.goods.length; i++) {
vm.all+= vm.goods[i].quantity* vm.goods[i].price;
}
vm.locationChange();
}, function(res) {
$state.go('home');
});
vm.locationChange = function() {
if(vm.state.name === "Минская область") {
if(vm.all< 200) {
vm.shipping= 20;
} else{
vm.shipping= 0;
}
} else if(vm.state.name === "Беларусь") {
if(vm.all< 500) {
vm.shipping= 50;
} else{
vm.shipping= 0;
}
} else{
if(vm.all< 100) {
vm.shipping= 10;
} else{
vm.shipping= 0;
}
}
vm.resume= vm.all+ vm.shipping;
}
});
Листинг файла public/template/about.html
<div ng-controller="aboutController as vm"><p class="lead">За шесть лет своей деятельности мы прошли большой путь от небольшой торговой точки до полноценного магазина товаров для животных. За это время нам удалось не только значительно расширить ассортимент представленных зоотоваров, но и самое важное - завоевать популярность среди владельцев домашних животных. Отличительными чертами нашего магазина стали умеренные цены, качественное обслуживание и большой выбор товаров для животных от ведущих мировых производителей.</p>
<p class="lead">Магазин имеет площадь 150 м2, разделен на секции. В настоящий момент ассортимент магазина постоянно расширяется и изменяется. В продаже всегда есть товары, которые популярны благодаря своему отличному соотношению цены и качества. Мы можем предложить вам только те товары, которые уже проверены временем и пользуются заслуженной популярностью у владельцев домашних животных. Для постоянных клиентов действуют скидочные карты 3-5%, проводятся акции и предлагаются скидки на различные категории зоотоваров.</p>
<p class="lead">Наш телефон для связи: + 375 29 187-55-64</p>
</div>
Листинг файла public/template/cart.html
<div ng-controller="cartController as vm"><div ng-if="vm.error">
<div class="card card-inverse card-danger text-center">
<div class="card-block">
<blockquote class="card-blockquote">Вы не авторизовались и не можете заказывать товары</blockquote>
</div>
</div>
</div>
<div ng-if="!vm.error">
<table class="table">
<thead>
<tr>
<th>Товар</th>
<th>Количество</th>
<th>Цена</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in vm.goods">
<td><img class="categoryImgTumb" src="/img/{{item.img}}"> {{item.name}}</td>
<td>{{item.quantity}}</td>
<td>{{item.quantity* item.price}}</td>
</tr>
<tr>
<td>Итого</td>
<td></td>
<td>{{vm.all}}</td>
</tr>
</tbody>
</table>
<form ng-if="vm.all">
<div class="form-group">
<select class="form-control" ng-options="location.name for location in vm.locations" ng-init="vm.state=vm.locations[0]" ng-model="vm.state" ng-change="vm.locationChange()" required>
</select>
</div>
<div class="form-group">
<input class="form-control" placeholder="Ваш адрес" ng-model="vm.address" required>
</div>
<div class="form-group">
<span>Стоимость доставки: {{vm.shipping}}</span>
</div>
<div class="form-group">
<span>Итого включая доставку: {{vm.resume}}</span>
</div>
<div class="form-group">
</div>
<div class="form-group">
<button class="btn btn-primary btn-block">Подтвердить заказ</button>
</div>
</form>
</div>
</div>
Листинг файла public/template/categories.html
<div ng-controller="categoriesController as vm"><div ng-if="vm.error">
<div class="card card-inverse card-danger text-center"