diff --git a/03-components/10-MeetupView/MeetupView.js b/03-components/10-MeetupView/MeetupView.js index c2715d1..662619c 100644 --- a/03-components/10-MeetupView/MeetupView.js +++ b/03-components/10-MeetupView/MeetupView.js @@ -1,5 +1,5 @@ -import { defineComponent } from 'vue' -import { UiAlert, UiContainer } from '@shgk/vue-course-ui' +import {defineComponent} from 'vue' +import {UiAlert, UiContainer} from '@shgk/vue-course-ui' import MeetupAgenda from './MeetupAgenda.js' import MeetupDescription from './MeetupDescription.js' import MeetupCover from './MeetupCover.js' @@ -7,40 +7,51 @@ import MeetupInfo from './MeetupInfo.js' import './MeetupView.css' export default defineComponent({ - name: 'MeetupView', - - components: { - UiAlert, - UiContainer, - }, - - template: ` -
- - - - -
-
-

Описание

- - - -

Программа

- - - - - -
-
- - - -
-
+ name: 'MeetupView', + + components: { + UiAlert, + UiContainer, + MeetupCover, + MeetupDescription, + MeetupInfo, + MeetupAgenda + }, + + props: { + meetup: { + type: Object, + require: true + }, + }, + + template: ` +
+ + + +
+
+

Описание

+ + + +

Программа

+ + + + + Программа пока пуста... + +
+
+ + + +
+
+
+
- -
- `, + `, }) diff --git a/03-components/20-UiClock/UiClock.js b/03-components/20-UiClock/UiClock.js index 8215f32..7877c20 100644 --- a/03-components/20-UiClock/UiClock.js +++ b/03-components/20-UiClock/UiClock.js @@ -1,9 +1,31 @@ -import { defineComponent } from 'vue' +import {defineComponent, onMounted, onUnmounted, ref} from 'vue' +const INTERVAL = 1000; export default defineComponent({ - name: 'UiClock', + name: 'UiClock', - setup() {}, + setup() { + const currentTime = ref(null); + let timer = 0; - template: `
10:12:02
`, + function setCurrentTime() { + currentTime.value = new Date().toLocaleTimeString(navigator.language, {timeStyle: 'medium'}); + } + + onMounted(() => { + timer = setInterval(() => setCurrentTime(), INTERVAL) + setCurrentTime() + }) + + onUnmounted (() => { + clearInterval(timer) + }) + + return { + currentTime + } + }, + + template: ` +
{{ currentTime }}
`, }) diff --git a/03-components/30-removable-emails/EmailList.js b/03-components/30-removable-emails/EmailList.js index 7c8096e..c84a9ab 100644 --- a/03-components/30-removable-emails/EmailList.js +++ b/03-components/30-removable-emails/EmailList.js @@ -2,27 +2,30 @@ import { defineComponent } from 'vue' import EmailListItem from './EmailListItem.js' export default defineComponent({ - name: 'EmailList', + name: 'EmailList', - components: { - EmailListItem, - }, + components: { + EmailListItem, + }, - props: { - emails: { - type: Array, - required: true, + props: { + emails: { + type: Array, + required: true, + }, }, - }, - template: ` - - `, + emits: ['remove'], + + template: ` + + `, }) diff --git a/03-components/30-removable-emails/EmailListItem.js b/03-components/30-removable-emails/EmailListItem.js index c88ef26..ed33f49 100644 --- a/03-components/30-removable-emails/EmailListItem.js +++ b/03-components/30-removable-emails/EmailListItem.js @@ -1,24 +1,26 @@ -import { defineComponent } from 'vue' +import {defineComponent} from 'vue' export default defineComponent({ - name: 'EmailListItem', + name: 'EmailListItem', - props: { - email: { - type: String, - required: true, - }, + props: { + email: { + type: String, + required: true, + }, - marked: { - type: Boolean, - default: false, + marked: { + type: Boolean, + default: false, + }, }, - }, - template: ` -
  • - {{ email }} - -
  • - `, + emits: ['click-del'], + + template: ` +
  • + {{ email }} + +
  • + `, }) diff --git a/03-components/30-removable-emails/MarkedEmailsApp.js b/03-components/30-removable-emails/MarkedEmailsApp.js index 5e77151..24ffa50 100644 --- a/03-components/30-removable-emails/MarkedEmailsApp.js +++ b/03-components/30-removable-emails/MarkedEmailsApp.js @@ -1,75 +1,75 @@ -import { computed, defineComponent, ref } from 'vue' -import { UiFormGroup, UiInput } from '@shgk/vue-course-ui' +import {computed, defineComponent, ref} from 'vue' +import {UiFormGroup, UiInput} from '@shgk/vue-course-ui' import EmailList from './EmailList.js' // Значения взяты из https://jsonplaceholder.typicode.com/comments export function getEmails() { - return [ - 'Eliseo@gardner.biz', - 'Jayne_Kuhic@sydney.com', - 'Nikita@garfield.biz', - 'Lew@alysha.tv', - 'Hayden@althea.biz', - 'Presley.Mueller@myrl.com', - 'Dallas@ole.me', - 'Mallory_Kunze@marie.org', - 'Meghan_Littel@rene.us', - 'Carmen_Keeling@caroline.name', - 'Veronica_Goodwin@timmothy.net', - 'Oswald.Vandervort@leanne.org', - 'Kariane@jadyn.tv', - 'Nathan@solon.io', - 'Maynard.Hodkiewicz@roberta.com', - 'Christine@ayana.info', - 'Preston_Hudson@blaise.tv', - 'Vincenza_Klocko@albertha.name', - 'Madelynn.Gorczany@darion.biz', - 'Mariana_Orn@preston.org', - 'Noemie@marques.me', - 'Khalil@emile.co.uk', - 'Sophia@arianna.co.uk', - 'Jeffery@juwan.us', - 'Isaias_Kuhic@jarrett.net', - ] + return [ + 'Eliseo@gardner.biz', + 'Jayne_Kuhic@sydney.com', + 'Nikita@garfield.biz', + 'Lew@alysha.tv', + 'Hayden@althea.biz', + 'Presley.Mueller@myrl.com', + 'Dallas@ole.me', + 'Mallory_Kunze@marie.org', + 'Meghan_Littel@rene.us', + 'Carmen_Keeling@caroline.name', + 'Veronica_Goodwin@timmothy.net', + 'Oswald.Vandervort@leanne.org', + 'Kariane@jadyn.tv', + 'Nathan@solon.io', + 'Maynard.Hodkiewicz@roberta.com', + 'Christine@ayana.info', + 'Preston_Hudson@blaise.tv', + 'Vincenza_Klocko@albertha.name', + 'Madelynn.Gorczany@darion.biz', + 'Mariana_Orn@preston.org', + 'Noemie@marques.me', + 'Khalil@emile.co.uk', + 'Sophia@arianna.co.uk', + 'Jeffery@juwan.us', + 'Isaias_Kuhic@jarrett.net', + ] } export default defineComponent({ - name: 'MarkedEmailsApp', + name: 'MarkedEmailsApp', - components: { - UiFormGroup, - UiInput, - EmailList, - }, + components: { + UiFormGroup, + UiInput, + EmailList, + }, - setup() { - const emails = ref(getEmails()) - const query = ref('') + setup() { + const emails = ref(getEmails()) + const query = ref('') - const markedEmails = computed(() => { - return emails.value.map(email => ({ - email, - isMarked: !!(query.value && email.toLowerCase().includes(query.value.toLowerCase())), - })) - }) + const markedEmails = computed(() => { + return emails.value.map(email => ({ + email, + isMarked: !!(query.value && email.toLowerCase().includes(query.value.toLowerCase())), + })) + }) - function removeEmailByIndex(index) { - emails.value.splice(index, 1) - } + function removeEmailByIndex(index) { + emails.value.splice(index, 1) + } - return { - query, - markedEmails, - removeEmailByIndex, - } - }, + return { + query, + markedEmails, + removeEmailByIndex, + } + }, - template: ` -
    - - - - -
    - `, + template: ` +
    + + + + +
    + `, }) diff --git a/03-components/40-UiCounter/UiCounter.js b/03-components/40-UiCounter/UiCounter.js index 48ae865..22bdc13 100644 --- a/03-components/40-UiCounter/UiCounter.js +++ b/03-components/40-UiCounter/UiCounter.js @@ -1,23 +1,65 @@ -import { defineComponent } from 'vue' -import { UiButton } from '@shgk/vue-course-ui' +import {defineComponent, toRef} from 'vue' +import {UiButton} from '@shgk/vue-course-ui' import './UiCounter.css' export default defineComponent({ - name: 'UiCounter', - - components: { - UiButton, - }, - - setup() { - // Рекомендуется для практики реализовать обработку событий внутри setup, а не непосредственно в шаблоне - }, - - template: ` -
    - - 3 - -
    - `, + name: 'UiCounter', + + components: { + UiButton, + }, + + props: { + count: { + type: Number, + required: true, + }, + + min: { + type: Number, + default: 0 + }, + + max: { + type: Number, + default: Infinity + }, + }, + + setup(props, { emit }) { + // Рекомендуется для практики реализовать обработку событий внутри setup, а не непосредственно в шаблоне + const countTemp = toRef(() => props.count); + + function decrementCount() { + const newValue = countTemp.value - 1; + emit('update:count', newValue) + } + + function incrementCount() { + const newValue = countTemp.value + 1; + emit('update:count', newValue) + } + + return { + countTemp, + decrementCount, + incrementCount + } + }, + + template: ` +
    + + {{ countTemp }} + +
    + `, }) diff --git a/03-components/50-weather-components/WeatherApp.js b/03-components/50-weather-components/WeatherApp.js index 5fb34c3..74db91f 100644 --- a/03-components/50-weather-components/WeatherApp.js +++ b/03-components/50-weather-components/WeatherApp.js @@ -1,52 +1,38 @@ import { defineComponent } from 'vue' -import { getWeatherData, WeatherConditionIcons } from './weather.service.ts' +import { getWeatherData } from './weather.service.ts' +import WeatherCard from "./components/WeatherCard.js"; import './WeatherApp.css' + + export default defineComponent({ - name: 'WeatherApp', - - template: ` -
    -

    Погода в Средиземье

    - -
      -
    • -
      - ⚠️ - Королевская метеослужба короля Арагорна II: Предвещается наступление сильного шторма. -
      -
      -

      - Гондор -

      -
      - 07:17 -
      -
      -
      -
      ⛈️
      -
      15.0 °C
      -
      -
      -
      -
      Давление, мм рт. ст.
      -
      754
      -
      -
      -
      Влажность, %
      -
      90
      -
      -
      -
      Облачность, %
      -
      100
      -
      -
      -
      Ветер, м/с
      -
      10.5
      -
      -
      -
    • -
    -
    - `, + name: 'WeatherApp', + + components: { + WeatherCard + }, + + setup() { + const weatherData = getWeatherData(); + + return { + weatherData + } + }, + + template: ` +
    +

    Погода в Средиземье

    + +
      + +
    +
    + `, }) + diff --git a/03-components/50-weather-components/components/WeatherCard.js b/03-components/50-weather-components/components/WeatherCard.js new file mode 100644 index 0000000..113c295 --- /dev/null +++ b/03-components/50-weather-components/components/WeatherCard.js @@ -0,0 +1,65 @@ +import { defineComponent } from 'vue' +import WeatherCardAlert from "./WeatherCardAlert.js"; +import WeatherCardConditions from "./WeatherCardConditions.js"; +import WeatherCardDetails from "./WeatherCardDetails.js"; + + +function isDayNow(currientTime, sunriseTime, sunsetTime) { + return sunriseTime < currientTime && currientTime < sunsetTime; +} + +function pressureConvert(pressure) { + return Math.round(pressure * 0.75 ); +} + +export default defineComponent({ + name: 'WeatherCard', + + components: { + WeatherCardAlert, + WeatherCardConditions, + WeatherCardDetails + }, + + props: { + data: { + type: Object, + require: true + } + }, + + setup() { + return { + isDayNow, + pressureConvert + } + }, + + template: ` +
  • + + +
    +

    + {{ data.geographic_name }} +

    +
    + {{ data.current.dt }} +
    +
    + + + + +
  • + `, +}) diff --git a/03-components/50-weather-components/components/WeatherCardAlert.js b/03-components/50-weather-components/components/WeatherCardAlert.js new file mode 100644 index 0000000..49b4d85 --- /dev/null +++ b/03-components/50-weather-components/components/WeatherCardAlert.js @@ -0,0 +1,20 @@ +import { defineComponent } from 'vue' + +export default defineComponent({ + name: 'WeatherCardAlert', + + props: { + alert: { + type: Object, + require: true + } + }, + + template: ` +
    + ⚠️ + {{ alert.sender_name }}: + {{ alert.description }} +
    + `, +}) diff --git a/03-components/50-weather-components/components/WeatherCardConditions.js b/03-components/50-weather-components/components/WeatherCardConditions.js new file mode 100644 index 0000000..40b7858 --- /dev/null +++ b/03-components/50-weather-components/components/WeatherCardConditions.js @@ -0,0 +1,48 @@ +import { defineComponent } from 'vue' +import { WeatherConditionIcons } from '../weather.service.ts' + +function getIconByConditionId(id) { + return WeatherConditionIcons[parseInt(id)] || ''; +} + +function kelvinToCelsius(tempK) { + return (tempK - 273.15).toFixed(1); +} + + +export default defineComponent({ + name: 'WeatherCardConditions', + + props: { + id: { + type: Number, + require: true + }, + + temp: { + type: Number, + require: true + }, + + title: { + type: String, + default: '' + }, + }, + + setup() { + return { + getIconByConditionId, + kelvinToCelsius + } + }, + + template: ` +
    +
    + {{ getIconByConditionId(id) }} +
    +
    {{ kelvinToCelsius(temp) }} °C
    +
    + `, +}) diff --git a/03-components/50-weather-components/components/WeatherCardDetails.js b/03-components/50-weather-components/components/WeatherCardDetails.js new file mode 100644 index 0000000..b111238 --- /dev/null +++ b/03-components/50-weather-components/components/WeatherCardDetails.js @@ -0,0 +1,58 @@ +import { defineComponent } from 'vue' + +function pressureConvert(pressure) { + return Math.round(pressure * 0.75 ); +} + +export default defineComponent({ + name: 'WeatherCardDetails', + + props: { + clouds: { + type: Number || String, + default: '--' + }, + + humidity: { + type: Number || String, + default: '--' + }, + + pressure: { + type: Number, + require: true + }, + + windSpeed: { + type: Number || String, + default: '--' + }, + }, + + setup() { + return { + pressureConvert + } + }, + + template: ` +
    +
    +
    Давление, мм рт. ст.
    +
    {{ pressureConvert(pressure) }}
    +
    +
    +
    Влажность, %
    +
    {{ humidity }}
    +
    +
    +
    Облачность, %
    +
    {{ clouds }}
    +
    +
    +
    Ветер, м/с
    +
    {{ windSpeed }}
    +
    +
    + `, +}) diff --git a/04-sfc/10-MeetupView-script-setup/MeetupAgenda.vue b/04-sfc/10-MeetupView-script-setup/MeetupAgenda.vue index d5dee66..24f1ec1 100644 --- a/04-sfc/10-MeetupView-script-setup/MeetupAgenda.vue +++ b/04-sfc/10-MeetupView-script-setup/MeetupAgenda.vue @@ -1,20 +1,11 @@ - diff --git a/04-sfc/10-MeetupView-script-setup/MeetupAgendaItem.vue b/04-sfc/10-MeetupView-script-setup/MeetupAgendaItem.vue index 5674dd3..9df1741 100644 --- a/04-sfc/10-MeetupView-script-setup/MeetupAgendaItem.vue +++ b/04-sfc/10-MeetupView-script-setup/MeetupAgendaItem.vue @@ -1,108 +1,94 @@ - diff --git a/04-sfc/10-MeetupView-script-setup/MeetupCover.vue b/04-sfc/10-MeetupView-script-setup/MeetupCover.vue index b53fc38..157afc2 100644 --- a/04-sfc/10-MeetupView-script-setup/MeetupCover.vue +++ b/04-sfc/10-MeetupView-script-setup/MeetupCover.vue @@ -1,62 +1,53 @@ - diff --git a/04-sfc/10-MeetupView-script-setup/MeetupDescription.vue b/04-sfc/10-MeetupView-script-setup/MeetupDescription.vue index c8f4185..2f813cb 100644 --- a/04-sfc/10-MeetupView-script-setup/MeetupDescription.vue +++ b/04-sfc/10-MeetupView-script-setup/MeetupDescription.vue @@ -1,14 +1,8 @@ - diff --git a/04-sfc/10-MeetupView-script-setup/MeetupInfo.vue b/04-sfc/10-MeetupView-script-setup/MeetupInfo.vue index 1daf6c5..4392bc4 100644 --- a/04-sfc/10-MeetupView-script-setup/MeetupInfo.vue +++ b/04-sfc/10-MeetupView-script-setup/MeetupInfo.vue @@ -1,77 +1,63 @@ - diff --git a/04-sfc/10-MeetupView-script-setup/MeetupView.vue b/04-sfc/10-MeetupView-script-setup/MeetupView.vue index 1250e12..31bfc17 100644 --- a/04-sfc/10-MeetupView-script-setup/MeetupView.vue +++ b/04-sfc/10-MeetupView-script-setup/MeetupView.vue @@ -1,89 +1,95 @@ - diff --git a/04-sfc/20-MeetupCover-style-v-bind/MeetupCover.vue b/04-sfc/20-MeetupCover-style-v-bind/MeetupCover.vue index fbbc245..758625c 100644 --- a/04-sfc/20-MeetupCover-style-v-bind/MeetupCover.vue +++ b/04-sfc/20-MeetupCover-style-v-bind/MeetupCover.vue @@ -1,54 +1,52 @@ diff --git a/04-sfc/30-UiStretch/UiStretch.vue b/04-sfc/30-UiStretch/UiStretch.vue index 237c492..5a043c4 100644 --- a/04-sfc/30-UiStretch/UiStretch.vue +++ b/04-sfc/30-UiStretch/UiStretch.vue @@ -12,9 +12,9 @@ height: 100%; } -.stretch-container > img, -.stretch-container > video, -.stretch-container > picture { +.stretch-container > :slotted(img), +.stretch-container > :slotted(video), +.stretch-container > :slotted(picture) { object-fit: scale-down; }