diff --git a/apps/app/src/App.tsx b/apps/app/src/App.tsx index 5ffa2bb7..b21072cf 100644 --- a/apps/app/src/App.tsx +++ b/apps/app/src/App.tsx @@ -1,11 +1,7 @@ import { Router } from './router/Router'; function App() { - return ( - <> - - - ); + return ; } export default App; diff --git a/apps/app/src/assets/icons/check-1.svg b/apps/app/src/assets/icons/check-1.svg new file mode 100644 index 00000000..2f84cf14 --- /dev/null +++ b/apps/app/src/assets/icons/check-1.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/app/src/assets/icons/rating-star-1.svg b/apps/app/src/assets/icons/rating-star-1.svg new file mode 100644 index 00000000..32d2756e --- /dev/null +++ b/apps/app/src/assets/icons/rating-star-1.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/app/src/assets/images/aras-logo-temp.svg b/apps/app/src/assets/images/aras-logo-temp.svg new file mode 100644 index 00000000..93b279d7 --- /dev/null +++ b/apps/app/src/assets/images/aras-logo-temp.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/app/src/assets/images/thumbnailUrl-temp.png b/apps/app/src/assets/images/thumbnailUrl-temp.png new file mode 100644 index 00000000..305e4fe6 Binary files /dev/null and b/apps/app/src/assets/images/thumbnailUrl-temp.png differ diff --git a/apps/app/src/components/ScheduleCard/ScheduleCard.module.scss b/apps/app/src/components/ScheduleCard/ScheduleCard.module.scss new file mode 100644 index 00000000..510d7696 --- /dev/null +++ b/apps/app/src/components/ScheduleCard/ScheduleCard.module.scss @@ -0,0 +1,209 @@ +.scheduleCard { + background-color: $black-5; + display: flex; + gap: 14px; + flex-direction: column; + border-radius: 16px; + box-sizing: border-box; + padding: 24px; + + .addedToSchedule { + background-color: $black-10; + box-sizing: border-box; + padding: 8px; + border-radius: 8px; + gap: 10px; + display: flex; + + .ratingStar { + height: 16px; + width: 16px; + } + + .label { + margin: 0; + @include heading-4; + text-transform: uppercase; + } + } + + .timeAndArrow { + display: flex; + justify-content: space-between; + align-items: center; + + .time { + @include tag-14; + margin: 0; + } + + .arrowDown { + cursor: pointer; + transform: rotate(180deg); + transition: transform 0.3s ease-in-out; + + &.collapsed { + transform: rotate(0deg); + } + } + } + + .tag { + display: flex; + align-items: center; + gap: 8px; + + .theme { + background-color: $primary-muted-orange; + @include tag-14; + margin: 0; + color: white; + height: 24px; + width: 46px; + border-radius: 100%; + display: flex; + justify-content: center; + align-items: center; + } + + .label { + @include tag-14; + margin: 0; + } + } + + .eventName { + color: $primary-black; + @include paragraph-16; + margin: 0; + } + + .collapsibleContent { + display: flex; + flex-direction: column; + gap: 14px; + transition: + max-height 0.5s ease-in-out, + opacity 0.5s ease-in-out, + margin-top 0.5s ease-in-out; + max-height: 500px; + opacity: 1; + margin-top: 0; + + &.collapsed { + max-height: 0; + overflow: hidden; + opacity: 0; + margin-top: -16px; + } + } + + .eventDescription { + color: $black-70; + @include paragraph-16; + margin: 0; + } + + .divider { + padding-top: 6px; + width: 100%; + @include dottedBreak(rgba(23, 22, 21, 0.5)); + } + + .eventRequirements { + display: flex; + gap: 8px; + flex-direction: column; + + .mainLabel { + @include tag-14; + margin: 0; + margin-bottom: 10px; + } + + .requirement { + display: flex; + gap: 16px; + + .checkContainer { + height: 20px; + width: 20px; + background-color: $primary-muted-orange; + display: flex; + align-items: center; + justify-content: center; + border-radius: 100%; + + .check { + height: 8px; + width: 8px; + } + } + + .label { + margin: 0; + @include paragraph-16; + } + } + } + + .speakers { + display: flex; + flex-direction: column; + gap: 32px; + + .divider { + margin: -10px 0; + } + } + + .moderatorLabel { + @include tag-14; + margin: 0; + text-transform: uppercase; + } + + .speaker { + display: flex; + gap: 12px; + + .image { + width: 64px; + height: 67px; + } + + .speakerInfoWrapper { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 6px; + + .fullName { + @include tag-14; + text-transform: uppercase; + margin: 0; + } + + .title { + @include tag-14; + text-transform: uppercase; + color: $black-50; + margin: 0; + } + + .logoContainer { + max-height: 38px; + max-width: 80px; + .logo { + width: 100%; + height: 100%; + object-fit: contain; + } + } + } + } + + .button { + margin-top: 32px; + } +} diff --git a/apps/app/src/components/ScheduleCard/ScheduleCard.tsx b/apps/app/src/components/ScheduleCard/ScheduleCard.tsx new file mode 100644 index 00000000..7a3c716a --- /dev/null +++ b/apps/app/src/components/ScheduleCard/ScheduleCard.tsx @@ -0,0 +1,171 @@ +import c from './ScheduleCard.module.scss'; +import RatingStar from '../../assets/icons/rating-star-1.svg'; +import ArrowDown from '../../assets/icons/arrow-down-1.svg'; +import Check from '../../assets/icons/check-1.svg'; +import Button from '../Button'; +import { useState } from 'react'; +import clsx from 'clsx'; +import { EventWithSpeakerDto, Theme, EventType } from '@ddays-app/types'; + +type ScheduleCardProps = { + event: EventWithSpeakerDto; + isAddedToSchedule?: boolean; + clickHandler: () => void; +}; + +const ScheduleCard: React.FC = ({ + event, + isAddedToSchedule, + clickHandler, +}) => { + const [isOpen, setIsOpen] = useState(false); + + function getThemeLabel(eventTheme: Theme) { + switch (eventTheme) { + case Theme.Dev: + return 'DEV'; + case Theme.Design: + return 'DIZ'; + case Theme.Marketing: + return 'MARK'; + case Theme.Tech: + return 'TECH'; + } + } + + function getTypeLabel(eventType: EventType) { + switch (eventType) { + case EventType.Lecture: + return 'PREDAVANJE'; + case EventType.Workshop: + return 'RADIONICA'; + case EventType.FlyTalk: + return 'FLY TALK'; + case EventType.CampfireTalk: + return 'CAMPFIRE TALK'; + case EventType.Panel: + return 'PANEL'; + case EventType.Other: + return 'OSTALO'; + } + } + + function getTimeFromDate(date: string): string { + const dateObj = new Date(date); + const hours = String(dateObj.getHours()).padStart(2, '0'); + const minutes = String(dateObj.getMinutes()).padStart(2, '0'); + return `${hours}:${minutes}`; + } + + function getRequirements(eventRequirements: string) { + return eventRequirements.split( + '/', + ) as string[]; /* TODO: Prominit kada se sazna na koji je nacin ovaj podatak zapisan u bazi. Stilovi su spremni. */ + } + + return ( +
+ {isAddedToSchedule && ( +
+ Rating star +

Dodano u tvoj raspored

+
+ )} +
+

+ {getTimeFromDate(event.startsAt)} - {getTimeFromDate(event.endsAt)} +

+ Arrow pointing down setIsOpen((prev) => !prev)} + /> +
+
+
{getThemeLabel(event.theme as Theme)}
+

{getTypeLabel(event.type as EventType)}

+
+

{event.name}

+ +
+ {event.description && ( +

{event.description}

+ )} + + {event.requirements && ( + <> +
+
+

ZAHTJEVI:

+ {getRequirements(event.requirements).map((requirement, index) => ( +
+
+ Check +
+

{requirement}

+
+ ))} +
+ + )} +
+ +
+ {event.type === EventType.Panel && ( +

Voditelj panela:

+ )} +
+ {event.speakers && + event.speakers.map( + ( + speaker, + index, // Pod pretpostavkom da je moderator prvi u listi (ako je panel). + ) => ( + <> +
+ {speaker.firstName} +
+

+ {speaker.firstName} {speaker.lastName} +

+

{speaker.title}

+
+ +
+
+
+ {event.type === EventType.Panel && index === 0 && ( +
+ )} + + ), + )} +
+ + +
+ ); +}; + +export default ScheduleCard; diff --git a/apps/app/src/components/ScheduleCard/index.ts b/apps/app/src/components/ScheduleCard/index.ts new file mode 100644 index 00000000..4d25d6ea --- /dev/null +++ b/apps/app/src/components/ScheduleCard/index.ts @@ -0,0 +1,3 @@ +import ScheduleCard from './ScheduleCard'; + +export default ScheduleCard; diff --git a/apps/app/src/pages/TestPage/TestPage.tsx b/apps/app/src/pages/TestPage/TestPage.tsx new file mode 100644 index 00000000..fcd284db --- /dev/null +++ b/apps/app/src/pages/TestPage/TestPage.tsx @@ -0,0 +1,133 @@ +import ScheduleCard from '../../components/ScheduleCard'; +import ThumbnailTemp from '../../assets/images/thumbnailUrl-temp.png'; +import ArasLogo from '../../assets/images/aras-logo-temp.svg'; +import { useState } from 'react'; +import { EventWithSpeakerDto } from '@ddays-app/types'; + +const event = { + id: 1, + name: 'Tech Innovations Summit', + description: 'A deep dive into the latest trends in technology.', + startsAt: '2025-01-20T10:00:00Z', + endsAt: '2025-01-20T14:00:00Z', + maxParticipants: 300, + requirements: 'Basic understanding of cloud computing.', + footageLink: 'https://example.com/footage/tech-summit', + type: 'panel', + theme: 'tech', + codeId: 123, + speakers: [ + { + id: 1, + firstName: 'Jane', + lastName: 'Doe', + title: 'Software Engineer', + companyId: 101, + photo: { + mainPhotoUrl: 'https://example.com/photos/jane-doe-main.jpg', + thumbnailUrl: ThumbnailTemp, + }, + instagram: 'https://instagram.com/janedoe', + linkedin: 'https://linkedin.com/in/janedoe', + description: + 'Jane is a seasoned software engineer with expertise in cloud computing and distributed systems.', + company: { + id: 101, + category: 'gold', + name: 'Tech Innovations', + description: 'Leading the way in tech solutions.', + opportunitiesDescription: + 'We are hiring for multiple roles in AI and cloud engineering.', + website: 'https://techinnovations.com', + instagram: 'https://instagram.com/techinnovations', + linkedin: 'https://linkedin.com/company/techinnovations', + booth: 'A1', + logoImage: ArasLogo, + landingImage: 'https://example.com/images/landing/tech-innovations.jpg', + landingImageCompanyCulture: + 'https://example.com/images/culture/tech-innovations.jpg', + bookOfStandards: 'https://example.com/docs/tech-standards.pdf', + video: 'https://example.com/videos/intro.mp4', + interests: [ + { id: 201, name: 'Cloud Computing', theme: 'tech' }, + { id: 202, name: 'AI Research', theme: 'tech' }, + ], + jobs: [ + { + id: 301, + position: 'Cloud Engineer', + location: 'Remote', + details: 'Design and implement scalable cloud architectures.', + link: 'https://example.com/jobs/cloud-engineer', + createdAt: new Date(), + companyId: 101, + }, + ], + }, + }, + { + id: 2, + firstName: 'John', + lastName: 'Smith', + title: 'Creative Director', + companyId: 102, + photo: { + mainPhotoUrl: 'https://example.com/photos/john-smith-main.jpg', + thumbnailUrl: ThumbnailTemp, + }, + instagram: 'https://instagram.com/johnsmith', + linkedin: 'https://linkedin.com/in/johnsmith', + description: + 'John has over 15 years of experience in creative design and branding for global campaigns.', + company: { + id: 102, + category: 'silver', + name: 'Creative Minds', + description: 'Innovative design solutions for modern businesses.', + opportunitiesDescription: + 'Join our team of passionate designers and strategists.', + website: 'https://creativeminds.com', + instagram: 'https://instagram.com/creativeminds', + linkedin: 'https://linkedin.com/company/creativeminds', + booth: 'B5', + logoImage: ArasLogo, + landingImage: 'https://example.com/images/landing/creative-minds.jpg', + landingImageCompanyCulture: + 'https://example.com/images/culture/creative-minds.jpg', + bookOfStandards: 'https://example.com/docs/design-standards.pdf', + video: 'https://example.com/videos/intro.mp4', + interests: [ + { id: 203, name: 'Graphic Design', theme: 'design' }, + { id: 204, name: 'Brand Strategy', theme: 'design' }, + ], + jobs: [ + { + id: 302, + position: 'Brand Strategist', + location: 'On-site', + details: + 'Develop and implement brand strategies for Fortune 500 clients.', + link: 'https://example.com/jobs/brand-strategist', + createdAt: new Date(), + companyId: 102, + }, + ], + }, + }, + ], +}; + +const TestPage = () => { + const [isAddedToSchedule, setIsAddedToSchedule] = useState(false); + return ( + <> + setIsAddedToSchedule((prev) => !prev)} + /> + + ); +}; + +export default TestPage; diff --git a/apps/app/src/pages/TestPage/index.ts b/apps/app/src/pages/TestPage/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/apps/app/src/router/Router.tsx b/apps/app/src/router/Router.tsx index a9cdd9f0..d60e67c9 100644 --- a/apps/app/src/router/Router.tsx +++ b/apps/app/src/router/Router.tsx @@ -17,6 +17,7 @@ import { SchedulePage } from '../pages/SchedulePage'; import { ShoppingPage } from '../pages/ShoppingPage'; import { NavigationLayout } from '../layout'; import Home from '../pages/Home'; +import TestPage from '../pages/TestPage/TestPage'; const router = createBrowserRouter( createRoutesFromElements( @@ -32,6 +33,7 @@ const router = createBrowserRouter( } /> } /> + } /> } /> , ), diff --git a/apps/app/vite.config.ts.timestamp-1734547483838-91bec2620b317.mjs b/apps/app/vite.config.ts.timestamp-1734547483838-91bec2620b317.mjs new file mode 100644 index 00000000..b0601f4e --- /dev/null +++ b/apps/app/vite.config.ts.timestamp-1734547483838-91bec2620b317.mjs @@ -0,0 +1,28 @@ +// vite.config.ts +import { defineConfig } from "file:///C:/Users/tomic/Repositories/ddays-app/apps/app/node_modules/vite/dist/node/index.js"; +import react from "file:///C:/Users/tomic/Repositories/ddays-app/node_modules/@vitejs/plugin-react/dist/index.mjs"; +import path from "path"; +var __vite_injected_original_dirname = "C:\\Users\\tomic\\Repositories\\ddays-app\\apps\\app"; +var vite_config_default = defineConfig({ + plugins: [react()], + css: { + preprocessorOptions: { + scss: { + additionalData: ` + @import "./src/styles/colors.scss"; + @import "./src/styles/fonts.scss"; + @import "./src/styles/mixins.scss"; + ` + } + } + }, + resolve: { + alias: { + "@": path.resolve(__vite_injected_original_dirname, "./src") + } + } +}); +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJDOlxcXFxVc2Vyc1xcXFx0b21pY1xcXFxSZXBvc2l0b3JpZXNcXFxcZGRheXMtYXBwXFxcXGFwcHNcXFxcYXBwXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJDOlxcXFxVc2Vyc1xcXFx0b21pY1xcXFxSZXBvc2l0b3JpZXNcXFxcZGRheXMtYXBwXFxcXGFwcHNcXFxcYXBwXFxcXHZpdGUuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9DOi9Vc2Vycy90b21pYy9SZXBvc2l0b3JpZXMvZGRheXMtYXBwL2FwcHMvYXBwL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSc7XHJcbmltcG9ydCByZWFjdCBmcm9tICdAdml0ZWpzL3BsdWdpbi1yZWFjdCc7XHJcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlLmRldi9jb25maWcvXHJcbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XHJcbiAgcGx1Z2luczogW3JlYWN0KCldLFxyXG4gIGNzczoge1xyXG4gICAgcHJlcHJvY2Vzc29yT3B0aW9uczoge1xyXG4gICAgICBzY3NzOiB7XHJcbiAgICAgICAgYWRkaXRpb25hbERhdGE6IGBcclxuICAgICAgICAgIEBpbXBvcnQgXCIuL3NyYy9zdHlsZXMvY29sb3JzLnNjc3NcIjtcclxuICAgICAgICAgIEBpbXBvcnQgXCIuL3NyYy9zdHlsZXMvZm9udHMuc2Nzc1wiO1xyXG4gICAgICAgICAgQGltcG9ydCBcIi4vc3JjL3N0eWxlcy9taXhpbnMuc2Nzc1wiO1xyXG4gICAgICAgIGAsXHJcbiAgICAgIH0sXHJcbiAgICB9LFxyXG4gIH0sXHJcbiAgcmVzb2x2ZToge1xyXG4gICAgYWxpYXM6IHtcclxuICAgICAgJ0AnOiBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi9zcmMnKSxcclxuICAgIH0sXHJcbiAgfSxcclxufSk7XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBMFUsU0FBUyxvQkFBb0I7QUFDdlcsT0FBTyxXQUFXO0FBQ2xCLE9BQU8sVUFBVTtBQUZqQixJQUFNLG1DQUFtQztBQUt6QyxJQUFPLHNCQUFRLGFBQWE7QUFBQSxFQUMxQixTQUFTLENBQUMsTUFBTSxDQUFDO0FBQUEsRUFDakIsS0FBSztBQUFBLElBQ0gscUJBQXFCO0FBQUEsTUFDbkIsTUFBTTtBQUFBLFFBQ0osZ0JBQWdCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxNQUtsQjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFDQSxTQUFTO0FBQUEsSUFDUCxPQUFPO0FBQUEsTUFDTCxLQUFLLEtBQUssUUFBUSxrQ0FBVyxPQUFPO0FBQUEsSUFDdEM7QUFBQSxFQUNGO0FBQ0YsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K