index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. <template>
  2. <div :class="['nav-bar', { 'nav-bar--fixed': fixed }]">
  3. <div class="nav-bar-left">
  4. <div class="nav-icons">
  5. <i v-if="showNavIcons" class="icon-menu" @click="showMenu = true"></i>
  6. <router-link class="icon-logo" to="/"></router-link>
  7. <i v-if="showNavIcons" class="icon-mine" @click="onClickMine"></i>
  8. </div>
  9. <transition
  10. v-if="showNavIcons"
  11. enter-active-class="fadeIn"
  12. leave-active-class="fadeOut"
  13. >
  14. <div v-show="showMenu" class="nav-menu nav-links">
  15. <div class="nav-menu-header">
  16. <i class="logo"></i>
  17. <i class="close" @click="showMenu = false"></i>
  18. </div>
  19. <div class="nav-menu-body">
  20. <ul class="nav-links-inner">
  21. <li class="nav-link">
  22. <router-link to="/repaire/appointment"
  23. >REPAIR BOOKING</router-link
  24. >
  25. </li>
  26. <li class="nav-link">
  27. <router-link to="/fill-order">ONLINE SHOP</router-link>
  28. </li>
  29. <li class="nav-link">PTC Care Plus</li>
  30. <li class="nav-link">SOTRE LOCATION</li>
  31. <li class="nav-link">CONTACT US</li>
  32. </ul>
  33. </div>
  34. </div>
  35. </transition>
  36. </div>
  37. <div v-if="showNavIcons" class="nav-bar-right">
  38. <div class="user pointer flex-ac" @click="onClickMine">
  39. <template v-if="state.userInfo">
  40. <i class="icon-mine"></i>
  41. <span class="user-name">{{
  42. state.userInfo ? state.userInfo.name : 'Sign in'
  43. }}</span>
  44. </template>
  45. <span v-else class="u-no">LOGIN</span>
  46. </div>
  47. <div class="contact">
  48. <i class="icon-phone"></i>
  49. <div>
  50. <p class="tel">400-100-100</p>
  51. <p class="time">Mon-Fri &nbsp;9:00-17:00</p>
  52. </div>
  53. </div>
  54. </div>
  55. <transition enter-active-class="fadeIn" leave-active-class="fadeOut">
  56. <div
  57. v-if="state.userInfo"
  58. v-show="showMine"
  59. class="nav-menu nav-dropdown"
  60. :class="{ 'is-member': state.userInfo.orders.length }"
  61. >
  62. <div class="nav-menu-header">
  63. <i class="logo"></i>
  64. <i class="close" @click="showMine = false"></i>
  65. </div>
  66. <div class="nav-menu-body">
  67. <div class="info">
  68. <div class="p1">
  69. <p class="name">Hi, {{ state.userInfo.name }}</p>
  70. <p class="intro">
  71. {{ state.userInfo.orders.length ? 'Pro' : 'Ordinary' }} member
  72. </p>
  73. </div>
  74. <div v-if="!state.userInfo.orders.length" class="p2">
  75. <p class="txt">You have not purchased a member</p>
  76. <button class="btn" @click="$router.push('/fill-order')">
  77. BUY
  78. </button>
  79. </div>
  80. <div v-else class="p3">
  81. <div class="txt">
  82. $10 off for additional services |
  83. <strong class="primary">Buy now ></strong>
  84. </div>
  85. <div class="swiper">
  86. <div
  87. v-for="(item, index) of state.userInfo.orders"
  88. :key="index"
  89. class="swiper-item"
  90. >
  91. <div class="service">
  92. <div class="service-title">
  93. <i class="service-icon icon-lite"></i>
  94. <div class="service-type">{{ item.product_name }}</div>
  95. <div class="service-period">
  96. {{ item.start_time }} to {{ item.end_time }}
  97. </div>
  98. </div>
  99. <div class="service-model tac">{{ item.phone_info }}</div>
  100. <div class="service-code tac">{{ item.phone_imei }}</div>
  101. </div>
  102. </div>
  103. </div>
  104. <div v-if="state.userInfo.orders.length > 1" class="pagination">
  105. <i
  106. v-for="n of state.userInfo.orders.length"
  107. :key="n"
  108. class="dot active"
  109. ></i>
  110. </div>
  111. </div>
  112. </div>
  113. <div class="role">
  114. {{
  115. state.userInfo.orders.length
  116. ? 'Pro Member >'
  117. : 'Ordinary Member >'
  118. }}
  119. </div>
  120. <ul class="dropdown-list">
  121. <template v-if="state.userInfo.orders.length">
  122. <li class="dropdown-item i1">
  123. <router-link to="/repaire/history"
  124. >MY REPAIR REQUEST</router-link
  125. >
  126. </li>
  127. <li class="dropdown-item i2">
  128. <router-link to="/order">MY ORDER</router-link>
  129. </li>
  130. </template>
  131. <li class="dropdown-item i3">
  132. <router-link to="/gift-card">MY DISCOUNT COUPON</router-link>
  133. </li>
  134. <li class="dropdown-item i4">
  135. <router-link to="/invite"
  136. >INVITE FRIENDS
  137. <span class="ptc-tag">Get a $10 coupon</span></router-link
  138. >
  139. </li>
  140. <li class="dropdown-item i5">
  141. <router-link to="/account">ACCOUNT INFORMATION</router-link>
  142. </li>
  143. <li class="dropdown-item i6" @click="signOut">SIGN OUT</li>
  144. </ul>
  145. </div>
  146. </div>
  147. </transition>
  148. </div>
  149. </template>
  150. <script setup lang="ts">
  151. import { ref, watch } from 'vue'
  152. import { useRoute, useRouter } from 'vue-router'
  153. import { state, logout } from '@/store'
  154. import Dialog from '@/components/dialog'
  155. interface Props {
  156. showNavIcons?: boolean
  157. fixed?: boolean
  158. }
  159. defineProps<Props>()
  160. const router = useRouter()
  161. const route = useRoute()
  162. const showMenu = ref(false)
  163. const showMine = ref(false)
  164. watch(
  165. () => route.fullPath,
  166. () => {
  167. showMenu.value = showMine.value = false
  168. }
  169. )
  170. function onClickMine() {
  171. if (state.userInfo) {
  172. showMine.value = !showMine.value
  173. } else {
  174. router.push('/login')
  175. }
  176. }
  177. async function signOut() {
  178. await Dialog.confirm('TIPS', 'Are you sure you want to sign out?', {
  179. confirmText: 'YES',
  180. })
  181. await logout()
  182. router.push('/')
  183. }
  184. </script>
  185. <style lang="scss">
  186. :root {
  187. --nav-bar-height: 118px;
  188. @include media-breakpoint-up(md) {
  189. --nav-bar-height: 148px;
  190. }
  191. @include media-breakpoint-up(lg) {
  192. --nav-bar-height: 168px;
  193. }
  194. }
  195. .nav-bar {
  196. height: var(--nav-bar-height);
  197. background: #fff;
  198. border-bottom: 1px solid #d9d9d9;
  199. &--fixed {
  200. position: fixed;
  201. left: 0;
  202. top: 0;
  203. width: 100%;
  204. z-index: 10;
  205. }
  206. &-left {
  207. @include media-breakpoint-up(md) {
  208. display: flex;
  209. align-items: center;
  210. }
  211. }
  212. &-right {
  213. display: none;
  214. flex-shrink: 0;
  215. @include media-breakpoint-up(md) {
  216. display: flex;
  217. align-items: center;
  218. margin-left: 100px;
  219. .user .icon-mine {
  220. display: block;
  221. margin-right: 8px;
  222. width: 32px;
  223. height: 32px;
  224. }
  225. .user-name {
  226. font-size: 32px;
  227. font-weight: 600;
  228. color: $primary-color;
  229. }
  230. .u-no {
  231. font-size: 32px;
  232. color: #193059;
  233. }
  234. .contact {
  235. position: relative;
  236. display: none;
  237. margin-left: 30px;
  238. padding-left: 32px;
  239. &::before {
  240. content: '';
  241. position: absolute;
  242. left: 0;
  243. top: 50%;
  244. transform: translateY(-50%);
  245. width: 2px;
  246. height: 72px;
  247. background: #dae1ef;
  248. }
  249. }
  250. .tel {
  251. line-height: 44px;
  252. font-size: 32px;
  253. font-weight: 600;
  254. color: $primary-color;
  255. }
  256. .time {
  257. line-height: 44px;
  258. font-size: 32px;
  259. font-weight: 500;
  260. color: #999;
  261. }
  262. }
  263. @media (min-width: 1400px) {
  264. .contact {
  265. display: flex;
  266. align-items: center;
  267. }
  268. }
  269. }
  270. .nav-icons {
  271. box-sizing: content-box;
  272. position: relative;
  273. display: flex;
  274. justify-content: space-between;
  275. align-items: center;
  276. padding: 0 40px;
  277. height: var(--nav-bar-height);
  278. }
  279. .icon-menu {
  280. @include icon('@img/menu.png', 44px);
  281. }
  282. .icon-mine {
  283. @include icon('@img/user.png', 44px);
  284. }
  285. .icon-logo {
  286. @include icon('@img/logo.png', 130px, 70px);
  287. position: absolute;
  288. left: 50%;
  289. top: 50%;
  290. transform: translate(-50%, -50%);
  291. }
  292. .icon-phone {
  293. @include icon('@img/phone.png', 76px);
  294. margin-right: 26px;
  295. }
  296. @include media-breakpoint-up(md) {
  297. display: flex;
  298. justify-content: space-between;
  299. align-items: center;
  300. padding: 0 32px;
  301. .icon-menu,
  302. .icon-mine {
  303. display: none;
  304. }
  305. .icon-logo {
  306. position: static;
  307. margin-right: 32px;
  308. transform: none;
  309. }
  310. }
  311. @include media-breakpoint-up(lg) {
  312. padding: 0 120px;
  313. .icon-logo {
  314. margin-right: 126px;
  315. width: 207px;
  316. height: 99px;
  317. }
  318. }
  319. .nav-menu {
  320. display: flex;
  321. flex-direction: column;
  322. position: fixed;
  323. left: 0;
  324. right: 0;
  325. top: 0;
  326. bottom: 0;
  327. &-header {
  328. position: relative;
  329. display: flex;
  330. align-items: center;
  331. justify-content: center;
  332. height: var(--nav-bar-height);
  333. .logo {
  334. @include icon('@img/logo.png', 130px, 70px);
  335. }
  336. .close {
  337. @include icon('@img/close.png', 44px);
  338. position: absolute;
  339. top: 50%;
  340. transform: translateY(-50%);
  341. right: 40px;
  342. }
  343. }
  344. &-body {
  345. flex: 1;
  346. overflow: auto;
  347. }
  348. }
  349. .nav-links {
  350. background: $primary-color;
  351. @include media-breakpoint-up(md) {
  352. display: block !important;
  353. position: static;
  354. background: none;
  355. .nav-menu-header {
  356. display: none;
  357. }
  358. }
  359. .logo {
  360. background-image: url(@img/logo2.png);
  361. transform: scale(1.03);
  362. }
  363. .close {
  364. background-image: url(@img/close2.png);
  365. }
  366. }
  367. .nav-dropdown {
  368. background: #fff;
  369. @include media-breakpoint-up(md) {
  370. left: auto;
  371. right: 20px;
  372. bottom: auto;
  373. top: var(--nav-bar-height);
  374. margin-top: 2px;
  375. box-shadow: 0px 0px 28px 0px rgba(0, 0, 0, 0.08);
  376. z-index: 2;
  377. .nav-menu-header,
  378. .info,
  379. .ptc-tag {
  380. display: none;
  381. }
  382. .dropdown-list {
  383. margin-top: 0;
  384. }
  385. }
  386. @media (min-width: 1400px) {
  387. right: 520px;
  388. }
  389. }
  390. .nav-links-inner {
  391. margin-top: 36px;
  392. line-height: 144px;
  393. font-size: 40px;
  394. font-weight: 600;
  395. color: #fff;
  396. @include media-breakpoint-up(md) {
  397. display: flex;
  398. margin-top: 0;
  399. font-size: 28px;
  400. font-weight: 400;
  401. line-height: 44px;
  402. color: #193059;
  403. }
  404. @include media-breakpoint-up(lg) {
  405. font-size: 32px;
  406. }
  407. }
  408. .nav-link {
  409. padding-left: 196px;
  410. background-color: $primary-color;
  411. transition: background-color 0.3s ease;
  412. &:active {
  413. background-color: $primary-color-lighten;
  414. }
  415. @include media-breakpoint-up(md) {
  416. padding-left: 0;
  417. background-color: #fff !important;
  418. + .nav-link {
  419. margin-left: 48px;
  420. }
  421. }
  422. @include media-breakpoint-up(lg) {
  423. + .nav-link {
  424. margin-left: 64px;
  425. }
  426. }
  427. a {
  428. display: block;
  429. width: 100%;
  430. }
  431. }
  432. .info {
  433. margin: 20px auto 24px;
  434. width: 678px;
  435. }
  436. .p1 {
  437. padding: 48px 0 0 50px;
  438. height: 202px;
  439. color: $primary-color;
  440. background-color: #e9ebf0;
  441. background-repeat: no-repeat;
  442. background-size: 190px 190px;
  443. background-position: 446px 46px;
  444. background-image: url(@img/user-lg.png);
  445. border-radius: 8px 8px 0px 0px;
  446. .name {
  447. font-size: 48px;
  448. font-weight: 600;
  449. }
  450. .intro {
  451. margin-top: 16px;
  452. font-size: 32px;
  453. }
  454. }
  455. .p2 {
  456. padding: 48px;
  457. height: 224px;
  458. border-radius: 0 0 8px 8px;
  459. border: 2px solid #e9ebf0;
  460. .txt {
  461. line-height: 44px;
  462. font-size: 32px;
  463. color: #333;
  464. }
  465. .btn {
  466. display: block;
  467. margin-top: 24px;
  468. width: 144px;
  469. height: 60px;
  470. font-size: 32px;
  471. font-weight: 600;
  472. color: #fff;
  473. background: $primary-color;
  474. border-radius: 8px;
  475. &:active {
  476. background: $primary-color-lighten;
  477. }
  478. }
  479. }
  480. .p3 {
  481. height: 436px;
  482. border-radius: 0 0 8px 8px;
  483. background: #e9ebf0;
  484. .txt {
  485. padding: 24px 36px 24px 48px;
  486. font-size: 30px;
  487. color: #333;
  488. }
  489. .swiper {
  490. padding-left: 44px;
  491. }
  492. .service {
  493. padding: 26px 18px;
  494. width: 526px;
  495. height: 266px;
  496. background: #ffffff;
  497. border-radius: 8px;
  498. &-title {
  499. display: flex;
  500. align-items: center;
  501. font-size: 28px;
  502. }
  503. &-icon {
  504. margin-right: 10px;
  505. width: 36px;
  506. height: 36px;
  507. }
  508. &-type {
  509. margin-right: 30px;
  510. font-weight: bold;
  511. color: $primary-color;
  512. }
  513. &-period {
  514. color: #90a0c0;
  515. }
  516. &-model {
  517. margin-top: 48px;
  518. font-size: 40px;
  519. font-weight: 600;
  520. text-align: center;
  521. }
  522. &-code {
  523. margin-top: 8px;
  524. font-size: 28px;
  525. text-align: center;
  526. color: #999;
  527. }
  528. }
  529. .pagination {
  530. display: flex;
  531. justify-content: center;
  532. margin-top: 32px;
  533. .dot {
  534. width: 16px;
  535. height: 16px;
  536. border-radius: 50%;
  537. background: rgba(26, 48, 89, 0.3);
  538. &.active {
  539. background: $primary-color;
  540. }
  541. + .dot {
  542. margin-left: 24px;
  543. }
  544. }
  545. }
  546. }
  547. .is-member {
  548. .p1,
  549. .role {
  550. color: #fff;
  551. background-color: $primary-color;
  552. }
  553. .p1 {
  554. background-image: url(@img/pro-lg.png);
  555. background-position: 446px 64px;
  556. }
  557. }
  558. .role {
  559. display: none;
  560. line-height: 80px;
  561. text-align: center;
  562. font-size: 32px;
  563. font-weight: 600;
  564. color: #193059;
  565. background-color: #e9ebf0;
  566. @include media-breakpoint-up(md) {
  567. display: block;
  568. }
  569. }
  570. .dropdown-list {
  571. margin-top: 24px;
  572. }
  573. .dropdown-item {
  574. position: relative;
  575. display: flex;
  576. align-items: center;
  577. padding-left: 144px;
  578. line-height: 144px;
  579. font-size: 32px;
  580. color: #1a1a1a;
  581. background-color: #fff;
  582. background-position: 84px center;
  583. background-repeat: no-repeat;
  584. background-size: 32px 32px;
  585. transition: background-color 0.3s ease;
  586. cursor: pointer;
  587. @include media-breakpoint-up(md) {
  588. padding-left: 80px;
  589. padding-right: 24px;
  590. background-position: 24px center;
  591. font-size: 28px;
  592. line-height: 124px;
  593. }
  594. &:hover,
  595. &:active {
  596. background-color: #f2f5fb;
  597. }
  598. &.i1 {
  599. background-image: url(@img/m-repair.png);
  600. }
  601. &.i2 {
  602. background-image: url(@img/m-order.png);
  603. }
  604. &.i3 {
  605. background-image: url(@img/m-coupon.png);
  606. }
  607. &.i4 {
  608. background-image: url(@img/m-friend.png);
  609. }
  610. &.i5 {
  611. background-image: url(@img/m-info.png);
  612. }
  613. &.i6 {
  614. background-image: url(@img/m-exit.png);
  615. }
  616. a {
  617. display: block;
  618. width: 100%;
  619. }
  620. }
  621. }
  622. </style>