Vašou úlohou bude implementovať jednoduchú zákaznícku stránku na frontende v knižnici React v TypeScript. React aplikácia sa bude napájať na GraphQL server na získanie údajov a na REST API na sprístupnenie URL adresy obrázka. Skeleton projektu sa nachádza na githube. Použitie externých knižníc podľa vašich preferencií.
Dizajn nájdete na tejto URL adrese: https://www.figma.com/design/uIKNOAap7gIqOgXCTQloBD/Untitled?node-id=0-1&t=OmKUSUzJo2mADLA5-1
Prototyp: https://www.figma.com/proto/uIKNOAap7gIqOgXCTQloBD/Untitled?node-id=1-2&t=OmKUSUzJo2mADLA5-1
V rámci dizajnu poprosím o implementáciu dvoch podstránok:
Riadime sa prístupom mobile-first, takže dizajn je orientovaný prevažne na mobily, ale výsledné stránky musia byť responzívne. V prípade väčších rozlíšení môžete zobraziť viac informácií o evente.
V rámci jednoduchosti neimplementujte funkcionalitu ani dizajn prihlasovania a odhlasovania – namiesto toho dostanete token, cez ktorý budete môcť získavať dáta. Na stránke Moje rezervácie je implementácia funkcionality Trasa a položiek zo submenu Pridať do kalendára a pridať do kontaktov voliteľná. Všetky neimplementované položky z dizajnu ako v submenu (odhlásiť sa, pridať do kalendára...) a tlačidlá (trasa…) nadizajnujte bez nutnosti implementácie funkcionality.
Vytvorenie ďalšej rezervácie presmeruje používateľa na novú URL stránku: https://{{alias}}.snippet-test.myfox.cz/form/show.
Získanie obrázku realizujete na tejto URL adrese: https://api.myfox.cz/test/photo/{{secret}}. Autorizačný token nie je potrebný.
URL GraphQL servera: https://cmyp37vc53jlbv5wa3nrnez6mi0dktla.lambda-url.eu-central-1.on.aws/. Pre prístup k dátam využite tento testovací token v hlavičke vašich požiadaviek: "X-Api-Key": "da2-gcyvktbwpfhnznbpdaghdbyf7m"
ID zákazníka je „cm0b8kilabkyu0783rc2uuzax“.
Bude vás zaujímať najmä štyri modely:
Informácie ohľadom zákazníka, obrázok je v picture.
type Customer {
id: String!
createdAt: AWSDateTime!
name: String
surname: String
phone: String
email: String
address: String
locale: Locale
picture: File
}
Samotné rezervácie. Rezervácie so stavom Open patria do sekcie aktuálne rezervácie, zvyšok (okrem Canceled) patrí do „navštívte opäť“. Obrázok eventu je prvý záznam v carts -> item -> picture. Ak obrázok neexistuje, použite logo subjektu (microsite -> logo).
type Calendar {
id: String!
capacity: Int
eventType: EventType!
carts: [Cart!]
createdAt: AWSDateTime!
employees: [Employee!]
from: AWSDateTime
note: String
shop: Shop
subject: Subject
state: CalendarState!
to: AWSDateTime
updatedAt: AWSDateTime!
isOnlineReservation: Boolean
canBeCancelUntil: AWSDateTime
}
Informácie o prevádzke (adresa udalosti, telefónne číslo, názov...).
type Shop {
id: String!
name: String!
address: Address
email: String
phone: String
}
Informácie o samotnej firme. Tu vás bude zaujímať alias a logo (microsite -> logo).
type Subject {
id: String!
name: String
marketingName: String
alias: String!
address: Address
microsite: Microsite
customersLastChange: AWSDateTime
locale: Locale
currency: Currency
dic: String
ico: String
vatPayer: Boolean
}
type Employee {
id: String!
color: String
showCstContact: Boolean!
notifyPhone: String
receiptName: String
userMyFox: UserMyFox
}
type UserMyFox {
id: String!
address: String
email: String
name: String
phone: String
surname: String
locale: Locale
userPicture: File
}
Dôležité k vytvoreniu URL na obrázok
type File {
id: String!
secret: String!
}
type Cart {
id: String!
count: Int
item: Item
name: String!
price: Float
priceVat: Float!
vat: Float!
}
type Item {
id: String!
color: String!
code: String
stockEnabled: Boolean
warranty: String
manufacturer: String
duration: Int
pauseAfter: Int
pauseBefore: Int
name: String!
note: String
ord: Int
price: Float
priceVat: Float
picture: File
}
enum CalendarState {
Open
Paid
Canceled
Storno
Test
}
enum EventType {
Individual
Group
Unavailability
}
Použite na získanie údajov customer a calendars queries resolvers:
getCustomer(
where: CustomerWhereUniqueInput!
): Customer
type CustomerWhereUniqueInput {
id: String
}
listCalendars(where: CalendarWhereInput, orderBy: CalendarOrderByInput): [Calendar]!
type CalendarWhereInput {
id: StringFilter
capacity: IntNullableFilter
customers: CustomerFilter
employees: EmployeeFilter
state: CalendarStateEnumFilter
carts: CartFilter
from: AWSDateTimeNullableFilter
to: AWSDateTimeNullableFilter
eventType: EventTypeEnumFilter
}
type CustomerFilter {
some: CustomerWhereInputWithoutNullables
every: CustomerWhereInputWithoutNullables
none: CustomerWhereInputWithoutNullables
}
type CustomerWhereInputWithoutNullables {
id: StringFilter
createdAt: AWSDateTimeFilter
star: BooleanNullableFilter
updatedAt: AWSDateTimeFilter
warning: BooleanNullableFilter
name: StringNullableFilter
surname: StringNullableFilter
phone: StringNullableFilter
email: StringNullableFilter
}
type EmployeeFilter {
some: EmployeeWhereInputWithoutNullables
every: EmployeeWhereInputWithoutNullables
none: EmployeeWhereInputWithoutNullables
}
type EmployeeWhereInputWithoutNullables {
id: StringFilter
color: StringNullableFilter
createdAt: AWSDateTimeFilter
bookEnabled: BooleanFilter
showCstContact: BooleanFilter
notifyPhone: StringNullableFilter
ord: IntNullableFilter
receiptName: StringNullableFilter
}
type CartFilter {
some: CartWhereInputWithoutNullables
every: CartWhereInputWithoutNullables
none: CartWhereInputWithoutNullables
}
type CartWhereInputWithoutNullables {
id: StringFilter
count: IntNullableFilter
createdAt: AWSDateTimeFilter
name: StringFilter
priceVat: FloatFilter
updatedAt: AWSDateTimeFilter
vat: FloatFilter
price: FloatNullableFilter
}
type StringFilter {
contains: String
endsWith: String
equals: String
in: [String!]
not: StringFilter
notIn: [String!]
startsWith: String
mode: String
}
type AWSDateTimeFilter {
equals: AWSDateTime
gt: AWSDateTime
gte: AWSDateTime
in: [AWSDateTime!]
lt: AWSDateTime
lte: AWSDateTime
not: AWSDateTimeFilter
notIn: [AWSDateTime!]
}
type BooleanFilter {
equals: Boolean
not: BooleanFilter
}
type IntNullableFilter {
equals: Int
gt: Int
gte: Int
in: [Int!]
lt: Int
lte: Int
not: IntFilter
notIn: [Int!]
isNull: Boolean
}
type FloatFilter {
equals: Float
gt: Float
gte: Float
in: [Float!]
lt: Float
lte: Float
not: FloatFilter
notIn: [Float!]
isNull: Boolean
}
type CalendarStateEnumFilter {
equals: CalendarState
in: [CalendarState!]
not: CalendarStateEnumFilter
notIn: [CalendarState!]
}
type EventTypeEnumFilter {
equals: EventType
in: [EventType!]
not: EventTypeEnumFilter
notIn: [EventType!]
}
type CalendarOrderByInput {
id: OrderByArg
billNumber: OrderByArg
capacity: OrderByArg
createdAt: OrderByArg
from: OrderByArg
note: OrderByArg
paidAt: OrderByArg
payType: OrderByArg
eventType: OrderByArg
state: OrderByArg
to: OrderByArg
updatedAt: OrderByArg
}
enum OrderByArg {
ASC
DESC
}
Budete potrebovať len updateCustomer:
updateCustomer(
data: CustomerUpdateInput!
where: CustomerWhereUniqueInput!
): Customer
type CustomerUpdateInput {
name: String
surname: String
phone: String
email: String
address: String
locale: Locale
}
type CustomerWhereUniqueInput {
id: String
}
V prípade technických otázok k zadaniu ma kontaktujte na tejto emailovej adrese: lukco@myfox.cz
Tvoja úloha bude implementovať jednoduchou zákaznickou stránku na front-endu v knihovně React v TypeScriptu. React aplikace se bude napojovat na GraphQL server pro získání údajů a na REST API pro zpřístupnění URL adresy obrázku. Skeleton projektu se nachází na githubu. Použití externích knihoven je na vašich preferencích.
Design naleznete na této URL adrese: https://www.figma.com/design/uIKNOAap7gIqOgXCTQloBD/Untitled?node-id=0-1&t=OmKUSUzJo2mADLA5-1
Prototyp: https://www.figma.com/proto/uIKNOAap7gIqOgXCTQloBD/Untitled?node-id=1-2&t=OmKUSUzJo2mADLA5-1
V rámci designu prosím o implementaci dvou podstránek:
Řídíme se přístupem mobile-first, takže design je orientovaný převážně na mobily, ale výsledné stránky musí být responzivní. V případě větších rozlišení můžete zobrazit více informací o události.
V rámci jednoduchosti neimplementujte funkcionalitu ani design přihlašování a odhlašování – místo toho dostanete token, přes který budete moci získávat data. Na stránce Moje rezervace je implementace funkcionality Trasa a položek ze submenu Přidat do kalendáře a přidat do kontaktů volitelná. Všechny neimplementované položky z designu jako v submenu (odhlásit se, přidat do kalendáře...) a tlačítka (trasa…) nadizajnujte bez nutnosti implementace funkcionality.
Vytvoření další rezervace přesměruje uživatele na novou URL stránku: https://{{alias}}.snippet-test.myfox.cz/form/show.
Obrázek získáte na této URL adrese: https://api.myfox.cz/test/photo/{{secret}}. Autorizační token není potřebný.
URL GraphQL serveru: https://cmyp37vc53jlbv5wa3nrnez6mi0dktla.lambda-url.eu-central-1.on.aws/. Pro přístup k datům využijte tento testovací token v hlavičkách vašich požadavků: "X-Api-Key": "da2-gcyvktbwpfhnznbpdaghdbyf7m"
ID zákazníka je „cm0b8kilabkyu0783rc2uuzax“.
Bude vás zajímat především čtyři modely:
Informace o zákazníkovi, obrázek je v picture.
type Customer {
id: String!
createdAt: AWSDateTime!
name: String
surname: String
phone: String
email: String
address: String
locale: Locale
picture: File
}
Samotné rezervace. Rezervace se stavem Open patří do sekce aktuální rezervace, zbytek (kromě Canceled) patří do „navštivte znovu“. Obrázek události je první záznam v carts -> item -> picture. Pokud obrázek neexistuje, použijte logo subjektu (microsite -> logo).
type Calendar {
id: String!
capacity: Int
eventType: EventType!
carts: [Cart!]
createdAt: AWSDateTime!
employees: [Employee!]
from: AWSDateTime
note: String
shop: Shop
subject: Subject
state: CalendarState!
to: AWSDateTime
updatedAt: AWSDateTime!
isOnlineReservation: Boolean
canBeCancelUntil: AWSDateTime
}
Informace o provozovně (adresa události, telefonní číslo, název...).
type Shop {
id: String!
name: String!
address: Address
email: String
phone: String
}
Informace o samotné firmě. Zde vás bude zajímat alias a logo (microsite -> logo).
type Subject {
id: String!
name: String
marketingName: String
alias: String!
address: Address
microsite: Microsite
customersLastChange: AWSDateTime
locale: Locale
currency: Currency
dic: String
ico: String
vatPayer: Boolean
}
type Employee {
id: String!
color: String
showCstContact: Boolean!
notifyPhone: String
receiptName: String
userMyFox: UserMyFox
}
type UserMyFox {
id: String!
address: String
email: String
name: String
phone: String
surname: String
locale: Locale
userPicture: File
}
Důležité k vytvoření URL na obrázek
type File {
id: String!
secret: String!
}
type Cart {
id: String!
count: Int
item: Item
name: String!
price: Float
priceVat: Float!
vat: Float!
}
type Item {
id: String!
color: String!
code: String
stockEnabled: Boolean
warranty: String
manufacturer: String
duration: Int
pauseAfter: Int
pauseBefore: Int
name: String!
note: String
ord: Int
price: Float
priceVat: Float
picture: File
}
enum CalendarState {
Open
Paid
Canceled
Storno
Test
}
enum EventType {
Individual
Group
Unavailability
}
Použijte na získání údajů customer a calendars queries resolvery:
getCustomer(
where: CustomerWhereUniqueInput!
): Customer
type CustomerWhereUniqueInput {
id: String
}
listCalendars(where: CalendarWhereInput, orderBy: CalendarOrderByInput): [Calendar]!
type CalendarWhereInput {
id: StringFilter
capacity: IntNullableFilter
customers: CustomerFilter
employees: EmployeeFilter
state: CalendarStateEnumFilter
carts: CartFilter
from: AWSDateTimeNullableFilter
to: AWSDateTimeNullableFilter
eventType: EventTypeEnumFilter
}
type CustomerFilter {
some: CustomerWhereInputWithoutNullables
every: CustomerWhereInputWithoutNullables
none: CustomerWhereInputWithoutNullables
}
type CustomerWhereInputWithoutNullables {
id: StringFilter
createdAt: AWSDateTimeFilter
star: BooleanNullableFilter
updatedAt: AWSDateTimeFilter
warning: BooleanNullableFilter
name: StringNullableFilter
surname: StringNullableFilter
phone: StringNullableFilter
email: StringNullableFilter
}
type EmployeeFilter {
some: EmployeeWhereInputWithoutNullables
every: EmployeeWhereInputWithoutNullables
none: EmployeeWhereInputWithoutNullables
}
type EmployeeWhereInputWithoutNullables {
id: StringFilter
color: StringNullableFilter
createdAt: AWSDateTimeFilter
bookEnabled: BooleanFilter
showCstContact: BooleanFilter
notifyPhone: StringNullableFilter
ord: IntNullableFilter
receiptName: StringNullableFilter
}
type CartFilter {
some: CartWhereInputWithoutNullables
every: CartWhereInputWithoutNullables
none: CartWhereInputWithoutNullables
}
type CartWhereInputWithoutNullables {
id: StringFilter
count: IntNullableFilter
createdAt: AWSDateTimeFilter
name: StringFilter
priceVat: FloatFilter
updatedAt: AWSDateTimeFilter
vat: FloatFilter
price: FloatNullableFilter
}
type StringFilter {
contains: String
endsWith: String
equals: String
in: [String!]
not: StringFilter
notIn: [String!]
startsWith: String
mode: String
}
type AWSDateTimeFilter {
equals: AWSDateTime
gt: AWSDateTime
gte: AWSDateTime
in: [AWSDateTime!]
lt: AWSDateTime
lte: AWSDateTime
not: AWSDateTimeFilter
notIn: [AWSDateTime!]
}
type BooleanFilter {
equals: Boolean
not: BooleanFilter
}
type IntNullableFilter {
equals: Int
gt: Int
gte: Int
in: [Int!]
lt: Int
lte: Int
not: IntFilter
notIn: [Int!]
isNull: Boolean
}
type FloatFilter {
equals: Float
gt: Float
gte: Float
in: [Float!]
lt: Float
lte: Float
not: FloatFilter
notIn: [Float!]
isNull: Boolean
}
type CalendarStateEnumFilter {
equals: CalendarState
in: [CalendarState!]
not: CalendarStateEnumFilter
notIn: [CalendarState!]
}
type EventTypeEnumFilter {
equals: EventType
in: [EventType!]
not: EventTypeEnumFilter
notIn: [EventType!]
}
type CalendarOrderByInput {
id: OrderByArg
billNumber: OrderByArg
capacity: OrderByArg
createdAt: OrderByArg
from: OrderByArg
note: OrderByArg
paidAt: OrderByArg
payType: OrderByArg
eventType: OrderByArg
state: OrderByArg
to: OrderByArg
updatedAt: OrderByArg
}
enum OrderByArg {
ASC
DESC
}
Budete potřebovat pouze updateCustomer:
updateCustomer(
data: CustomerUpdateInput!
where: CustomerWhereUniqueInput!
): Customer
type CustomerUpdateInput {
name: String
surname: String
phone: String
email: String
address: String
locale: Locale
}
type CustomerWhereUniqueInput {
id: String
}
V případě technických dotazů k úkolu mě kontaktujte na této emailové adrese: lukco@myfox.cz