feat: add comprehensive ServiceMenu and MainTabs components with hotel service listings, QR code access, and user profile settings integration

This commit is contained in:
louiscklaw
2025-06-19 23:06:51 +08:00
parent a68cb01585
commit 76840a8e1b
28 changed files with 1053 additions and 143 deletions

View File

@@ -10,6 +10,12 @@
"jsonRecursiveSort": false,
"jsonSortOrder": "{\"*\": \"lexical\"}",
"overrides": [
{
"files": "src/pages/MainTabs/index.tsx",
"options": {
"printWidth": 240
}
},
{
"files": "src/App.tsx",
"options": {

View File

@@ -70,7 +70,7 @@ import DummyPayPage from './pages/DummyEventPayPage';
import DummyEventPayPage from './pages/DummyEventPayPage';
import PaymentSuccess from './pages/PaymentSuccess';
import PaymentFailed from './pages/PaymentFailed';
import CarousellMe from './pages/CarousellMe';
import settings from './pages/tabs/carousell_me/settings';
setupIonicReact();
@@ -159,9 +159,9 @@ const IonicApp: React.FC<IonicAppProps> = ({ darkMode, schedule, setIsLoggedIn,
/>
{/* PartyUser */}
<Route path={PATHS.PARTY_USER_SIGN_IN} component={PartyUserLogin} />
<Route exact={true} path={PATHS.PARTY_USER_SIGN_IN} component={PartyUserLogin} />
<Route exact={true} path={PATHS.NOT_IMPLEMENTED} component={NotImplemented} />
<Route exact={true} path={PATHS.CAROUSELL_ME_SETTINGS} component={settings} />
<Route path="/" component={HomeOrTutorial} exact />
</IonRouterOutlet>

View File

@@ -105,5 +105,7 @@ const PATHS = {
//
CAROUSELL_ME: '/tabs/carousell_me',
CAROUSELL_ME_QR: '/tabs/carousell_me/qr_page',
CAROUSELL_ME_SETTINGS: '/tabs/carousell_me/settings',
};
export default PATHS;

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.4" d="M16.19 2H7.81C4.17 2 2 4.17 2 7.81V16.18C2 19.83 4.17 22 7.81 22H16.18C19.82 22 21.99 19.83 21.99 16.19V7.81C22 4.17 19.83 2 16.19 2Z" fill="#292D32"/>
<path d="M13.0594 12.0001L15.3594 9.70011C15.6494 9.41011 15.6494 8.93011 15.3594 8.64011C15.0694 8.35011 14.5894 8.35011 14.2994 8.64011L11.9994 10.9401L9.69937 8.64011C9.40937 8.35011 8.92937 8.35011 8.63938 8.64011C8.34938 8.93011 8.34938 9.41011 8.63938 9.70011L10.9394 12.0001L8.63938 14.3001C8.34938 14.5901 8.34938 15.0701 8.63938 15.3601C8.78938 15.5101 8.97937 15.5801 9.16937 15.5801C9.35937 15.5801 9.54937 15.5101 9.69937 15.3601L11.9994 13.0601L14.2994 15.3601C14.4494 15.5101 14.6394 15.5801 14.8294 15.5801C15.0194 15.5801 15.2094 15.5101 15.3594 15.3601C15.6494 15.0701 15.6494 14.5901 15.3594 14.3001L13.0594 12.0001Z" fill="#292D32"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,46 @@
import React from 'react';
import { IonList, IonItem, IonLabel, IonText } from '@ionic/react';
import closeSvg from './close.svg';
interface CloseButtonProps {
onClick: (e: React.UIEvent) => void;
}
const CloseButton: React.FC<CloseButtonProps> = ({ onClick }) => {
return (
<>
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
width: '25vw',
height: '25vw',
maxWidth: '100px',
maxHeight: '100px',
}}
>
<div
style={{
height: '100%',
width: '100%',
backgroundImage: `url("${closeSvg}")`,
backgroundSize: 'contain',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
}}
onClick={onClick}
/>
<IonText>
<h5>Close</h5>
</IonText>
</div>
</>
);
};
export default React.memo(CloseButton);

View File

@@ -63,10 +63,18 @@ import { format, parseISO } from 'date-fns';
// import lookForVisitorSvg from './look_for_visitor.svg';
const SellingButton: React.FC = () => {
const router = useIonRouter();
return (
<>
<div style={{ width: '50%' }}>
<IonCard style={{ margin: '0.5rem' }} button onClick={(e) => console.log('helloworld')}>
<IonCard
style={{ margin: '0.5rem' }}
button
onClick={(e) => {
window.location.href =
'https://www.carousell.com.hk/p/coding-javascript-python-vba-freelance-1192889425/';
}}
>
<img
alt="Silhouette of mountains"
src="https://ionicframework.com/docs/img/demos/card-media.png"
@@ -127,17 +135,12 @@ const ListingsContent: React.FC<SessionListProps> = ({ hide }) => {
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-evenly',
justifyContent: 'flex-start',
}}
>
<SellingButton />
<SellingButton />
<SellingButton />
<SellingButton />
<SellingButton />
<SellingButton />
<SellingButton />
<SellingButton />
</div>
</div>
</>

View File

@@ -34,7 +34,9 @@ import {
IonSegmentButton,
useIonRouter,
} from '@ionic/react';
import './style.scss';
import {
locationSharp,
settingsOutline,
@@ -56,6 +58,9 @@ import {
heartSharp,
heartOutline,
chatbubblesOutline,
heart,
chatbubbles,
chatbox,
} from 'ionicons/icons';
import AboutPopover from '../../components/AboutPopover';
import { format, parseISO } from 'date-fns';
@@ -67,8 +72,13 @@ import ReviewsContent from './ReviewsContent';
import ListingsContent from './ListingsContent';
import { triggerShare } from '../../util/triggerShare';
import { connect } from '../../data/connect';
import PATHS from '../../PATHS';
// import { toProperCase } from 'src/util/toProperCase';
import './theme/variables.scss';
import { messages } from '../DemoFacebookClone/main/messages';
import { Router } from 'react-router';
interface OwnProps {}
interface StateProps {
@@ -133,16 +143,43 @@ const CarousellMe: React.FC<CarousellMeProps> = () => {
<IonToolbar>
<IonButtons slot="end">
<IonButton onClick={presentPopover}>
<IonIcon slot="icon-only" icon={heartOutline}></IonIcon>
<div>
<IonIcon slot="icon-only" icon={heartOutline} size="large"></IonIcon>
</div>
</IonButton>
<IonButton onClick={presentPopover}>
<IonIcon slot="icon-only" icon={chatbubblesOutline}></IonIcon>
<IonBadge style={{ backgroundColor: 'white', color: 'black' }}>1</IonBadge>
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<IonIcon slot="icon-only" icon={chatbox} size="large"></IonIcon>
<div
style={{
color: 'black',
fontWeight: 'bold',
//
position: 'relative',
height: 0,
top: '-1.5rem',
//
fontSize: '0.8rem',
}}
>
<div>99</div>
</div>
</div>
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
{/* */}
{/* */}
{/* */}
<div className="about-header">
{/* Instead of loading an image each time the select changes, use opacity to transition them */}
<div
@@ -153,19 +190,18 @@ const CarousellMe: React.FC<CarousellMeProps> = () => {
}}
></div>
</div>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '1.5rem',
gap: '0.5rem',
paddingLeft: '1rem',
paddingRight: '1rem',
}}
>
<div className="profile-test">
<img
src="https://avatars.githubusercontent.com/u/1376093"
src="https://media.karousell.com/media/photos/profiles/2025/02/05/louis_coding_1738774979_f1598e0b.jpg"
style={{
height: '75px',
width: '75px',
@@ -175,7 +211,7 @@ const CarousellMe: React.FC<CarousellMeProps> = () => {
/>
<div className="setting-icons">
<IonButton fill="clear" onClick={handleShareLink}>
<IonButton shape="round" fill="clear" onClick={handleShareLink}>
<IonIcon
color="primary"
slot="icon-only"
@@ -184,13 +220,15 @@ const CarousellMe: React.FC<CarousellMeProps> = () => {
></IonIcon>
</IonButton>
<IonButton fill="clear" routerLink="/tabs/carousell_me/qr_page">
<IonButton shape="round" fill="clear" routerLink={PATHS.CAROUSELL_ME_QR}>
<IonIcon color="primary" slot="icon-only" ios={qrCode} md={qrCode}></IonIcon>
</IonButton>
<IonButton
shape="round"
fill="clear"
routerLink="/tabs/carousell_me/settings"
routerLink={PATHS.CAROUSELL_ME_SETTINGS}
// onClick={() => route.push(PATHS.CAROUSELL_ME_SETTINGS, 'forward', 'push')}
// onClick={handleSettingPageClick}
>
<IonIcon
@@ -203,8 +241,8 @@ const CarousellMe: React.FC<CarousellMeProps> = () => {
</div>
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
<div style={{ fontWeight: 'bold' }}>Louis Law</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.25rem' }}>
<div style={{ fontWeight: 'bold' }}>louis_coding</div>
<div
style={{
fontSize: '0.9rem',
@@ -213,7 +251,7 @@ const CarousellMe: React.FC<CarousellMeProps> = () => {
gap: '0.8rem',
}}
>
<IonText color="medium">@louiscklaw</IonText>
<IonText color="medium">@louis_coding</IonText>
<div
style={{
display: 'flex',
@@ -321,7 +359,6 @@ const CarousellMe: React.FC<CarousellMeProps> = () => {
</div>
</div>
</div>
{/* listing / reviews / about */}
<IonSegment
mode={'md'}
@@ -333,7 +370,6 @@ const CarousellMe: React.FC<CarousellMeProps> = () => {
<IonSegmentButton value="about">{t('About')}</IonSegmentButton>
</IonSegment>
{/* listing / reviews / about */}
<ListingsContent hide={segment != 'listings'} />
<ReviewsContent hide={segment != 'reviews'} />
<AboutContent hide={segment != 'about'} />

View File

@@ -1,7 +1,13 @@
#carousell-me-page {
--ion-color-tertiary: #ad8e70;
--ion-color-tertiary-rgb: 173, 142, 112;
--ion-color-tertiary-contrast: #000000;
--ion-color-tertiary-contrast-rgb: 0, 0, 0;
--ion-color-tertiary-shade: #987d63;
--ion-color-tertiary-tint: #b5997e;
.setting-icons {
ion-button::part(native) {
// https://ionicframework.com/docs/theming/css-shadow-parts
margin: 0;
padding: 0;
}

View File

@@ -0,0 +1,59 @@
#carousell-me-page {
ion-button {
--ion-color-primary: #243763;
--ion-color-primary-rgb: 36, 55, 99;
--ion-color-primary-contrast: #ffffff;
--ion-color-primary-contrast-rgb: 255, 255, 255;
--ion-color-primary-shade: #203057;
--ion-color-primary-tint: #3a4b73;
--ion-color-secondary: #ff6e31;
--ion-color-secondary-rgb: 255, 110, 49;
--ion-color-secondary-contrast: #000000;
--ion-color-secondary-contrast-rgb: 0, 0, 0;
--ion-color-secondary-shade: #e0612b;
--ion-color-secondary-tint: #ff7d46;
--ion-color-tertiary: #ad8e70;
--ion-color-tertiary-rgb: 173, 142, 112;
--ion-color-tertiary-contrast: #000000;
--ion-color-tertiary-contrast-rgb: 0, 0, 0;
--ion-color-tertiary-shade: #987d63;
--ion-color-tertiary-tint: #b5997e;
--ion-color-success: #2dd36f;
--ion-color-success-rgb: 45, 211, 111;
--ion-color-success-contrast: #000000;
--ion-color-success-contrast-rgb: 0, 0, 0;
--ion-color-success-shade: #28ba62;
--ion-color-success-tint: #42d77d;
--ion-color-warning: #ffc409;
--ion-color-warning-rgb: 255, 196, 9;
--ion-color-warning-contrast: #000000;
--ion-color-warning-contrast-rgb: 0, 0, 0;
--ion-color-warning-shade: #e0ac08;
--ion-color-warning-tint: #ffca22;
--ion-color-danger: #eb445a;
--ion-color-danger-rgb: 235, 68, 90;
--ion-color-danger-contrast: #ffffff;
--ion-color-danger-contrast-rgb: 255, 255, 255;
--ion-color-danger-shade: #cf3c4f;
--ion-color-danger-tint: #ed576b;
--ion-color-medium: #92949c;
--ion-color-medium-rgb: 146, 148, 156;
--ion-color-medium-contrast: #000000;
--ion-color-medium-contrast-rgb: 0, 0, 0;
--ion-color-medium-shade: #808289;
--ion-color-medium-tint: #9d9fa6;
--ion-color-light: #ffebb7;
--ion-color-light-rgb: 255, 235, 183;
--ion-color-light-contrast: #000000;
--ion-color-light-contrast-rgb: 0, 0, 0;
--ion-color-light-shade: #e0cfa1;
--ion-color-light-tint: #ffedbe;
}
}

View File

@@ -1,98 +0,0 @@
// REQ0116/main-tab
import React from 'react';
import { IonTabs, IonRouterOutlet, IonTabBar, IonTabButton, IonIcon, IonLabel } from '@ionic/react';
import { Route, Redirect } from 'react-router';
import { calendar, location, informationCircle, people } from 'ionicons/icons';
import SchedulePage from './SchedulePage';
import SpeakerList from './SpeakerList';
import SpeakerDetail from './SpeakerDetail';
import SessionDetail from './SessionDetail';
import MapView from './MapView';
import About from './About';
import EventList from './EventList';
import MembersNearByList from './MembersNearByList';
import OrderList from './OrderList';
import MyProfile from './MyProfile';
import MessageList from './MessageList';
import PATHS from '../PATHS';
import Favourites from './Favourites';
import Helloworld from './Helloworld';
import TabAppRoute from '../TabAppRoute';
import CarousellMe from './CarousellMe';
interface MainTabsProps {}
const MainTabs: React.FC<MainTabsProps> = () => {
return (
<IonTabs>
<IonRouterOutlet>
{/* REQ0117/default-route */}
<Redirect exact path="/tabs" to="/tabs/events" />
{/*
Using the render method prop cuts down the number of renders your components will have due to route changes.
Use the component prop when your component depends on the RouterComponentProps passed in automatically.
*/}
<Route path="/tabs/schedule" render={() => <SchedulePage />} exact={true} />
<Route path="/tabs/speakers" render={() => <SpeakerList />} exact={true} />
<Route path="/tabs/speakers/:id" component={SpeakerDetail} exact={true} />
<Route path="/tabs/schedule/:id" component={SessionDetail} />
<Route path="/tabs/speakers/sessions/:id" component={SessionDetail} />
<Route path="/tabs/map" render={() => <MapView />} exact={true} />
<Route path="/tabs/about" render={() => <About />} exact={true} />
<Route path="/tabs/helloworld" render={() => <Helloworld />} exact={true} />
{/* */}
<Route path={PATHS.CAROUSELL_ME} render={() => <CarousellMe />} exact={true} />
{/*
<Route path="/tabs/carousell_me/insights" component={Insights} exact={true} />
<Route path="/tabs/carousell_me/OffersMade" component={OffersMade} exact={true} />
<Route path="/tabs/carousell_me/settings" component={Settings} exact={true} />
<Route path="/tabs/carousell_me/my_profile" component={MyProfile} exact={true} />
<Route path="/tabs/carousell_me/qr_page" component={QRPage} exact={true} />
*/}
{/* */}
<TabAppRoute />
</IonRouterOutlet>
{/* */}
<IonTabBar slot="bottom">
{/*
<IonTabButton tab="speakers" href={'/tabs/speakers'}>
<IonIcon icon={calendar} />
<IonLabel>Speakers</IonLabel>
</IonTabButton>
*/}
<IonTabButton tab="events" href={PATHS.EVENT_LIST}>
<IonIcon icon={calendar} />
<IonLabel>Event</IonLabel>
</IonTabButton>
<IonTabButton tab="nearby" href={PATHS.NEARBY_LIST}>
<IonIcon icon={people} />
<IonLabel>Nearby</IonLabel>
</IonTabButton>
{/*
<IonTabButton tab="orders" href={PATHS.ORDERS_LIST}>
<IonIcon icon={location} />
<IonLabel>Order</IonLabel>
</IonTabButton>
*/}
<IonTabButton disabled></IonTabButton>
<IonTabButton tab="message" href={PATHS.MESSAGE_LIST}>
<IonIcon icon={informationCircle} />
<IonLabel>Message</IonLabel>
</IonTabButton>
<IonTabButton tab="my_profile" href={PATHS.PROFILE}>
<IonIcon icon={informationCircle} />
<IonLabel>Profile</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
);
};
export default MainTabs;

View File

@@ -0,0 +1,34 @@
import { IonCard, IonImg } from '@ionic/react';
import React from 'react';
interface MenuButtonProps {
iconUrl: string;
buttonText: string;
targetUrl: string;
onClick: (e: React.UIEvent) => void;
}
const MenuButton: React.FC<MenuButtonProps> = ({ iconUrl, buttonText, targetUrl, onClick }) => {
return (
<>
<IonCard
button
href={targetUrl}
className="service-button"
style={{
width: '24%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'center',
}}
>
<IonImg src={iconUrl}></IonImg>
<div style={{ fontSize: '0.8rem', textAlign: 'center' }}>{buttonText}</div>
<div style={{ fontSize: '0.8rem', textAlign: 'center' }}>()</div>
</IonCard>
</>
);
};
export default React.memo(MenuButton);

View File

@@ -0,0 +1,135 @@
import {
IonButton,
IonButtons,
IonContent,
IonGrid,
IonHeader,
IonItem,
IonModal,
IonRow,
IonTitle,
IonToolbar,
useIonModal,
} from '@ionic/react';
import React, { useState } from 'react';
import CloseButton from '../../components/CloseButton';
import MenuButton from './MenuButton';
import { useTranslation } from 'react-i18next';
import './style.scss';
interface ServiceMenuProps {
hotelServiceMenu: any;
showCenterButton: boolean;
buttonSvg: any;
}
// bookmark: facilities, bottom drawer, ServiceMenu
const ServiceMenu: React.FC<ServiceMenuProps> = ({
buttonSvg,
showCenterButton,
hotelServiceMenu,
}) => {
const { t } = useTranslation();
const [drawerOpen, setDrawerOpen] = useState(false);
function dismiss() {
setDrawerOpen(false);
}
return (
<>
<IonModal
isOpen={drawerOpen}
id="main-tabs-modal"
style={{
display: drawerOpen ? 'flex' : 'none',
flexDirection: 'column',
justifyContent: 'flex-end',
}}
onWillDismiss={dismiss}
>
<div className="wrapper" style={{ paddingTop: '1rem', paddingBottom: '1rem' }}>
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h6>{t('Greetings from xxx hotel')}</h6>
<h4>{t('please enjoy our services')}</h4>
</div>
<div
style={{
width: '100%',
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
gap: '0.25rem',
rowGap: '1rem',
justifyContent: 'space-around',
marginTop: '1rem',
}}
>
{hotelServiceMenu.map((service: any, index: number) => (
<MenuButton
key={index}
iconUrl={service.icon}
buttonText={service.name}
onClick={(e) => console.log('archive ?')}
targetUrl={service.targetUrl}
/>
))}
</div>
<IonGrid>
<IonRow class="ion-justify-content-center" style={{ marginTop: '2rem' }}>
<IonItem button lines="none" onClick={dismiss}>
<CloseButton onClick={(e) => dismiss()} />
</IonItem>
</IonRow>
</IonGrid>
</div>
</IonModal>
{/* */}
<div
style={{
position: 'fixed',
zIndex: 102,
//
bottom: '20px',
width: '50px',
height: '50px',
backgroundColor: 'gold',
//
borderRadius: '10px',
left: 'calc( (100vw - 50px) / 2 )',
//
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
//
boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2), 0 6px 20px rgba(0, 0, 0, 0.19)',
}}
>
<div
style={{
height: '80%',
width: '80%',
backgroundImage: `url("${buttonSvg}")`,
backgroundPosition: 'center',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
}}
onClick={() => setDrawerOpen(true)}
></div>
</div>
</>
);
};
export default React.memo(ServiceMenu);

View File

@@ -0,0 +1,187 @@
// REQ0116/main-tab
//
import React, { useEffect, useState } from 'react';
import { IonTabs, IonRouterOutlet, IonTabBar, IonTabButton, IonIcon, IonLabel, IonButton } from '@ionic/react';
import { Route, Redirect } from 'react-router';
import { calendar, location, informationCircle, people } from 'ionicons/icons';
import SchedulePage from '../SchedulePage';
import SpeakerList from '../SpeakerList';
import SpeakerDetail from '../SpeakerDetail';
import SessionDetail from '../SessionDetail';
import MapView from '../MapView';
import About from '../About';
import EventList from '../EventList';
import MembersNearByList from '../MembersNearByList';
import OrderList from '../OrderList';
import MyProfile from '../MyProfile';
import MessageList from '../MessageList';
import PATHS from '../../PATHS';
import Favourites from '../Favourites';
import Helloworld from '../Helloworld';
import TabAppRoute from '../../TabAppRoute';
import CarousellMe from '../CarousellMe';
import ServiceMenu from './ServiceMenu';
//
import QRPage from '../tabs/carousell_me/QRPage';
//
import svgIcon1 from './icons/air-conditioning-cooling-heat-temperature-svgrepo-com.svg';
import svgIcon2 from './icons/alert-attention-caution-dangerous-warning-svgrepo-com.svg';
import svgIcon3 from './icons/alert-bell-call-message-sign-svgrepo-com.svg';
import svgIcon4 from './icons/assistance-business-person-reception-service-svgrepo-com.svg';
import svgIcon5 from './icons/bag-baggage-luggage-suitcase-travel-svgrepo-com.svg';
import svgIcon6 from './icons/baggage-bellhop-hotel-service-waiter-svgrepo-com.svg';
import svgIcon7 from './icons/bag-holiday-journey-suitcase-vacation-svgrepo-com.svg';
import svgIcon8 from './icons/banking-financial-money-payment-transaction-svgrepo-com.svg';
import svgIcon9 from './icons/bar-cafe-chair-club-stool-svgrepo-com.svg';
import svgIcon10 from './icons/bath-bathroom-cotton-textile-towel-svgrepo-com.svg';
import svgIcon11 from './icons/bathroom-bathtub-bubble-foam-water-svgrepo-com.svg';
import svgIcon12 from './icons/bathroom-faucet-room-sink-wash-svgrepo-com.svg';
import svgIcon13 from './icons/bed-furniture-interior-pillow-rest-2-svgrepo-com.svg';
import svgIcon14 from './icons/bed-furniture-interior-pillow-rest-3-svgrepo-com.svg';
import svgIcon15 from './icons/bed-furniture-interior-pillow-rest-svgrepo-com.svg';
import svgIcon16 from './icons/book-catalog-document-guidebook-instruction-svgrepo-com.svg';
import svgIcon17 from './icons/business-finance-money-saving-wallet-svgrepo-com.svg';
import svgIcon18 from './icons/cafe-card-food-menu-vintage-svgrepo-com.svg';
import svgIcon19 from './icons/cafe-cup-drink-mug-tea-svgrepo-com.svg';
import svgIcon20 from './icons/calendar-date-day-month-time-svgrepo-com.svg';
import svgIcon21 from './icons/cappuccino-coffee-cup-drink-espresso-2-svgrepo-com.svg';
import svgIcon22 from './icons/cappuccino-coffee-cup-drink-espresso-svgrepo-com.svg';
import svgIcon23 from './icons/card-credit-currency-finance-money-svgrepo-com.svg';
import svgIcon24 from './icons/card-door-key-lock-security-svgrepo-com.svg';
import svgIcon25 from './icons/chair-comfortable-decoration-garden-terrace-svgrepo-com.svg';
import svgIcon26 from './icons/clean-clothing-laundry-washing-wind-svgrepo-com.svg';
import svgIcon27 from './icons/comfortable-fabric-footwear-shoe-slipper-svgrepo-com.svg';
import svgIcon28 from './icons/coupon-entertainment-event-paper-ticket-svgrepo-com.svg';
import svgIcon29 from './icons/door-elevator-entrance-floor-lift-svgrepo-com.svg';
import svgIcon30 from './icons/door-enter-entry-exit-open-svgrepo-com.svg';
import svgIcon31 from './icons/door-entrance-handle-key-security-svgrepo-com.svg';
import svgIcon32 from './icons/door-key-lock-room-security-svgrepo-com.svg';
import svgIcon33 from './icons/electronic-internet-screen-technology-television-svgrepo-com.svg';
import svgIcon34 from './icons/holiday-hotel-journey-service-travel-2-svgrepo-com.svg';
import svgIcon35 from './icons/holiday-hotel-journey-service-travel-svgrepo-com.svg';
import svgIcon36 from './icons/holiday-hotel-motel-sign-travel-svgrepo-com.svg';
import svgIcon37 from './icons/holiday-journey-luggage-suitcase-vacation-2-svgrepo-com.svg';
import svgIcon38 from './icons/hotel-location-map-pin-travel-svgrepo-com.svg';
import getButtonSvg from '../../api/getButtonSvg';
//
const hotelServiceMenu = [
{ name: '停車場', icon: svgIcon1, targetUrl: '/tabs/hotel_service_intro' },
{ name: '接機服務', icon: svgIcon2, targetUrl: '/tabs/hotel_service_intro' },
{ name: '餐廳', icon: svgIcon3, targetUrl: '/tabs/hotel/:hotelid/restaurants' },
{ name: '咖啡室', icon: svgIcon4, targetUrl: '/tabs/restaurant/:restaurant_id/food/:food_id/intro' },
{ name: '酒吧', icon: svgIcon5, targetUrl: '/tabs/hotel_service_intro' },
{ name: '會議室', icon: svgIcon6, targetUrl: '/tabs/hotel_service_intro' },
{ name: '托兒服務', icon: svgIcon7, targetUrl: '/tabs/hotel_service_intro' },
{ name: '茶室', icon: svgIcon8, targetUrl: '/tabs/hotel_service_intro' },
{ name: '多功能室', icon: svgIcon9, targetUrl: '/tabs/hotel_service_intro' },
{ name: '商務便利設施', icon: svgIcon10, targetUrl: '/tabs/hotel_service_intro' },
{ name: '健身室', icon: svgIcon11, targetUrl: '/tabs/hotel_service_intro' },
{ name: '公共區域 Wi-Fi免費', icon: svgIcon12, targetUrl: '/tabs/hotel_service_intro' },
{ name: '貨幣兌換', icon: svgIcon13, targetUrl: '/tabs/hotel_service_intro' },
{ name: '行李寄存免費', icon: svgIcon14, targetUrl: '/tabs/hotel_service_intro' },
{ name: '叫醒服務', icon: svgIcon16, targetUrl: '/tabs/hotel_service_intro' },
{ name: '關於酒店', icon: svgIcon16, targetUrl: '/tabs/hotel_intro' },
];
interface MainTabsProps {}
const MainTabs: React.FC<MainTabsProps> = () => {
let [buttonSvg, setButtonSvg] = useState<string | null>(null);
let [mainTabVisible, setMainTabVisible] = useState<'bottom' | undefined>(undefined);
let [showCenterButton, setShowCenterButton] = useState(mainTabVisible == 'bottom');
const hideMainTab = () => {
setMainTabVisible(undefined);
setShowCenterButton(false);
};
const showMainTab = () => {
setMainTabVisible('bottom');
setShowCenterButton(true);
};
useEffect(() => {
getButtonSvg().then((res) => setButtonSvg(res));
}, []);
return (
<div>
<ServiceMenu buttonSvg={buttonSvg} hotelServiceMenu={hotelServiceMenu} showCenterButton={showCenterButton} />
{/* */}
<IonTabs>
<IonRouterOutlet>
{/* REQ0117/default-route */}
<Redirect exact path="/tabs" to="/tabs/events" />
{/*
Using the render method prop cuts down the number of renders your components will have due to route changes.
Use the component prop when your component depends on the RouterComponentProps passed in automatically.
*/}
<Route path="/tabs/schedule" render={() => <SchedulePage />} exact={true} />
<Route path="/tabs/speakers" render={() => <SpeakerList />} exact={true} />
<Route path="/tabs/speakers/:id" component={SpeakerDetail} exact={true} />
<Route path="/tabs/schedule/:id" component={SessionDetail} />
<Route path="/tabs/speakers/sessions/:id" component={SessionDetail} />
<Route path="/tabs/map" render={() => <MapView />} exact={true} />
<Route path="/tabs/about" render={() => <About />} exact={true} />
<Route path="/tabs/helloworld" render={() => <Helloworld />} exact={true} />
{/* */}
<Route path={PATHS.CAROUSELL_ME} render={() => <CarousellMe />} exact={true} />
<Route path={PATHS.CAROUSELL_ME_QR} component={QRPage} exact={true} />
{/*
<Route path="/tabs/carousell_me/insights" component={Insights} exact={true} />
<Route path="/tabs/carousell_me/OffersMade" component={OffersMade} exact={true} />
<Route path="/tabs/carousell_me/settings" component={Settings} exact={true} />
<Route path="/tabs/carousell_me/my_profile" component={MyProfile} exact={true} />
*/}
<TabAppRoute />
</IonRouterOutlet>
<IonTabBar slot="bottom">
{/*
<IonTabButton tab="speakers" href={'/tabs/speakers'}>
<IonIcon icon={calendar} />
<IonLabel>Speakers</IonLabel>
</IonTabButton>
*/}
<IonTabButton tab="events" href={PATHS.EVENT_LIST}>
<IonIcon icon={calendar} />
<IonLabel>Event</IonLabel>
</IonTabButton>
<IonTabButton tab="nearby" href={PATHS.NEARBY_LIST}>
<IonIcon icon={people} />
<IonLabel>Nearby</IonLabel>
</IonTabButton>
{/*
<IonTabButton tab="orders" href={PATHS.ORDERS_LIST}>
<IonIcon icon={location} />
<IonLabel>Order</IonLabel>
</IonTabButton>
*/}
<IonTabButton disabled></IonTabButton>
<IonTabButton tab="message" href={PATHS.MESSAGE_LIST}>
<IonIcon icon={informationCircle} />
<IonLabel>Message</IonLabel>
</IonTabButton>
<IonTabButton tab="my_profile" href={PATHS.PROFILE}>
<IonIcon icon={informationCircle} />
<IonLabel>Profile</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
</div>
);
};
export default MainTabs;

View File

@@ -0,0 +1,59 @@
// TODO: Shadow Parts, https://ionicframework.com/docs/theming/css-shadow-parts
ion-modal#main-tabs-modal {
// --width: fit-content;
--min-width: 250px;
--height: fit-content;
--border-radius: 1rem 1rem 0 0;
--box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4);
// display: flex;
// flex-direction: column;
// justify-content: flex-end;
}
ion-modal#main-tabs-modal h1 {
margin: 20px 20px 10px 20px;
}
ion-modal#main-tabs-modal ion-icon {
margin-right: 6px;
width: 48px;
height: 48px;
padding: 4px 0;
color: #aaaaaa;
}
ion-modal#main-tabs-modal .wrapper {
margin-bottom: 10px;
}
.colcenter {
display: flex;
flex-direction: row;
justify-content: center;
}
ion-item::part(native):hover {
color: green;
}
.service-button {
box-shadow: none;
margin: 0;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
gap: 0.5rem;
ion-img {
min-width: 80%;
height: 40px;
padding-bottom: 3px;
}
}

View File

@@ -0,0 +1,210 @@
import {
IonBackButton,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonPage,
IonPopover,
IonSegment,
IonSegmentButton,
IonText,
IonTitle,
IonToolbar,
useIonRouter,
useIonViewDidEnter,
} from '@ionic/react';
import { chevronBackOutline, star, starOutline } from 'ionicons/icons';
import React, { useContext, useEffect, useRef, useState } from 'react';
// import AboutPopover from '../../components/AboutPopover';
import { useIonAlert } from '@ionic/react';
import './style.scss';
import { AppContext } from '../../../../data/AppContext';
import { createGesture, Gesture } from '@ionic/react';
import { useTranslation } from 'react-i18next';
import QRCode from 'react-qr-code';
interface QRCodeProps {}
type SessionListProps = {
hide: boolean;
};
const MyCode: React.FC<SessionListProps> = ({ hide }) => {
if (hide) return <></>;
return (
<>
<IonContent>
<div style={{ background: 'white', padding: '16px', margin: '3rem' }}>
<QRCode
size={256}
style={{ height: 'auto', maxWidth: '100%', width: '100%' }}
value="http://louiscklaw.github.io"
viewBox={`0 0 256 256`}
/>
</div>
<div
style={{
margin: '3rem',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<IonText style={{ color: 'grey' }}>Scan to follow me on Carousell!</IonText>
</div>
</IonContent>
</>
);
};
const ScanCode: React.FC<SessionListProps> = ({ hide }) => {
if (hide) return <></>;
return (
<>
<IonContent>Scan code</IonContent>
</>
);
};
const QRPage: React.FC<QRCodeProps> = () => {
const [showPopover, setShowPopover] = useState(false);
const [popoverEvent, setPopoverEvent] = useState<MouseEvent>();
const [location, setLocation] = useState<'madison' | 'austin' | 'chicago' | 'seattle'>('madison');
const [conferenceDate, setConferenceDate] = useState('2047-05-17T00:00:00-05:00');
const [showAlert, hideAlert] = useIonAlert();
const { browser_store } = useContext(AppContext);
const refRectangle = useRef<HTMLDivElement>(null);
const [swipeType, setSwipeType] = useState();
const [deltaX, setDeltaX] = useState();
const [velocityX, setVelocityX] = useState();
const [swipeVerdict, setSwipeVerdict] = useState('helloworld');
const route = useIonRouter();
useEffect(() => {
if (swipeVerdict == 'swipe-left')
if (route.canGoBack() == true) {
route.goBack();
} else {
route.push('/tabs/schedule');
}
}, [swipeVerdict]);
const onMove = (detail: any) => {
const type = detail.type;
const currentX = detail.currentX;
const deltaX = detail.deltaX;
const velocityX = detail.velocityX;
setSwipeType(type);
setDeltaX(deltaX);
setVelocityX(velocityX);
if (type == 'pan')
if (Math.abs(deltaX) > 50)
if (velocityX > 0) {
setSwipeVerdict('swipe-right');
} else {
setSwipeVerdict('swipe-left');
}
};
useIonViewDidEnter(() => {
let gesture: any = {};
if (refRectangle?.current) {
gesture = createGesture({
gestureName: 'helloworld',
el: refRectangle.current,
onMove: (detail) => {
onMove(detail);
},
});
gesture.enable();
}
return () => {
if (gesture) {
// gesture?.destroy();
}
};
}, [refRectangle]);
const handleStoreWrite = () => {
(async () => {
await browser_store.set('hello', 'world');
})();
};
const handleStoreRead = () => {
(async () => {
console.log(await browser_store.get('hello'));
})();
};
const handleStoreClear = () => {
(async () => {
await browser_store.clear();
})();
};
const handleStoreRemove = () => {
(async () => {
await browser_store.remove('hello');
})();
};
const handleStoreKeys = () => {
(async () => {
console.dir(await browser_store.keys());
})();
};
const handleStoreLength = () => {
(async () => {
console.dir(await browser_store.length());
})();
};
const userInput = 'javascript:alert("Oh no!")';
const [segment, setSegment] = useState<'my_code' | 'scan_code'>('my_code');
const { t } = useTranslation();
const router = useIonRouter();
return (
<IonPage id="qr-page">
<IonHeader translucent={true} className="ion-no-border">
<IonToolbar>
<IonButtons slot="start">
<IonButton shape="round" onClick={() => router.goBack()}>
<IonIcon icon={chevronBackOutline}></IonIcon>
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent>
<IonSegment
mode={'md'}
value={segment}
onIonChange={(e) => setSegment(e.detail.value as any)}
>
<IonSegmentButton value="my_code">{t('My Code')}</IonSegmentButton>
<IonSegmentButton value="scan_code">{t('Scan Code')}</IonSegmentButton>
</IonSegment>
<MyCode hide={segment != 'my_code'} />
<ScanCode hide={segment != 'scan_code'} />
</IonContent>
</IonPage>
);
};
export default React.memo(QRPage);

View File

@@ -0,0 +1,2 @@
#qr-page {
}

View File

@@ -0,0 +1,161 @@
import {
IonBackButton,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonPage,
IonPopover,
IonTitle,
IonToolbar,
useIonRouter,
useIonViewDidEnter,
} from '@ionic/react';
import { chevronBackOutline, star, starOutline } from 'ionicons/icons';
import React, { useContext, useEffect, useRef, useState } from 'react';
// import AboutPopover from '../../components/AboutPopover';
import { useIonAlert } from '@ionic/react';
import './style.scss';
import {
ImgCouponSvg,
ImgDataSvg,
ImgNotebookSvg,
ImgPrinterSvg,
ImgRiceSvg,
ImgSuitcaseSvg,
ImgTruckSvg,
ImgVoiceSvg,
} from './svgs';
interface SettingProps {}
const Settings: React.FC<SettingProps> = () => {
const [showPopover, setShowPopover] = useState(false);
const [popoverEvent, setPopoverEvent] = useState<MouseEvent>();
const [location, setLocation] = useState<'madison' | 'austin' | 'chicago' | 'seattle'>('madison');
const [conferenceDate, setConferenceDate] = useState('2047-05-17T00:00:00-05:00');
const [showAlert, hideAlert] = useIonAlert();
// const { browser_store } = useContext(AppContext);
const refRectangle = useRef<HTMLDivElement>(null);
const [swipeType, setSwipeType] = useState();
const [deltaX, setDeltaX] = useState();
const [velocityX, setVelocityX] = useState();
const [swipeVerdict, setSwipeVerdict] = useState('helloworld');
const route = useIonRouter();
return (
<IonPage id="settings-page">
<IonHeader translucent={true} className="ion-no-border">
<IonToolbar>
<IonButtons slot="start">
<IonButton onClick={() => route.goBack()}>
<IonIcon slot="icon-only" icon={chevronBackOutline}></IonIcon>
</IonButton>
</IonButtons>
<IonButtons slot="end">
<IonButton onClick={() => {}}>
{false ? (
<IonIcon slot="icon-only" icon={star}></IonIcon>
) : (
<IonIcon slot="icon-only" icon={starOutline}></IonIcon>
)}
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Settings</IonTitle>
</IonToolbar>
</IonHeader>
<IonList>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgRiceSvg />
<IonLabel>Edit Profile</IonLabel>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgPrinterSvg />
<IonLabel>Quick and Auto reply</IonLabel>
</IonItem>
{/* help and support */}
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<h3>Help & Support</h3>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgSuitcaseSvg />
<IonLabel>Support Inbox</IonLabel>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgDataSvg />
<IonLabel>Help Centen</IonLabel>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgTruckSvg />
<IonLabel>Contact Us</IonLabel>
</IonItem>
{/* Theme */}
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<h3>Theme</h3>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgPrinterSvg />
<IonLabel>Dark Mode</IonLabel>
</IonItem>
{/* Settings & Privacy */}
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<h3>Settings & Privacy</h3>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgVoiceSvg />
<IonLabel>Change Password</IonLabel>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgVoiceSvg />
<IonLabel>Notificatinos</IonLabel>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgDataSvg />
<IonLabel>Auto-reserve items</IonLabel>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgPrinterSvg />
<IonLabel>Save Photos</IonLabel>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgSuitcaseSvg />
<IonLabel>Social Media</IonLabel>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgCouponSvg />
<IonLabel>About Carousell</IonLabel>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgTruckSvg />
<IonLabel>Logout</IonLabel>
</IonItem>
<IonItem lines="full" button routerLink="/tabs/carousell_me/my_profile">
<ImgVoiceSvg />
<IonLabel>Deactivate Account</IonLabel>
</IonItem>
</IonList>
</IonContent>
</IonPage>
);
};
export default React.memo(Settings);

View File

@@ -0,0 +1,2 @@
#sample-blank-page {
}

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M908.056 171.944c-1.512 40.128-35.696 72.24-77.88 72.24-42.192 0-76.456-32.112-77.88-72.24H597.024c-1.512 40.128-35.64 72.24-77.88 72.24-42.192 0-76.344-32.112-77.784-72.24H284.584c-1.408 40.128-35.656 72.24-77.848 72.24-42.264 0-76.384-32.112-77.856-72.24H0v680.104h128.88c1.472-40.136 35.592-72.24 77.856-72.24 42.2 0 76.44 32.112 77.848 72.24h156.768c1.44-40.136 35.592-72.24 77.784-72.24 42.24 0 76.368 32.112 77.88 72.24h155.264c1.432-40.136 35.688-72.24 77.88-72.24 42.184 0 76.368 32.112 77.88 72.24H1024V171.944h-115.944z" fill="#F5B146" /><path d="M173.96 519.384h640.424v131.328H173.96z" fill="#E5226B" /><path d="M173.96 379.704h279.168v65.68H173.96z" fill="#0092D2" /><path d="M174.36 408.184h278.296v37.192H174.36z" fill="#0085BF" /><path d="M174.36 583.48h640.896v67.232H174.36z" fill="#C9005B" /></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M54.296 225.944h841.8v670.336H54.296z" fill="#F6AB20" /><path d="M812.904 225.944H54.296v670.328h330.472z" fill="#F5A517" /><path d="M984.52 940.952H76.544a31.472 31.472 0 0 1-31.488-31.488V123.288c0-17.4 14.08-31.488 31.488-31.488s31.488 14.08 31.488 31.488v754.696h876.496a31.472 31.472 0 0 1 31.48 31.488 31.472 31.472 0 0 1-31.488 31.48z" fill="#E6246B" /><path d="M260.632 692.352a22.896 22.896 0 0 1-14.872-40.304l116.176-111.912a22.704 22.704 0 0 1 21.256-4.584l193.424 56.232 154.808-241.2a22.896 22.896 0 1 1 38.568 24.728L605.92 630.936a22.888 22.888 0 0 1-25.664 9.616L382.272 582.96 275.504 686.848a22.768 22.768 0 0 1-14.872 5.504z" fill="#0093D3" /></svg>

After

Width:  |  Height:  |  Size: 921 B

View File

@@ -0,0 +1,33 @@
import React from 'react';
import CouponSvg from './coupon.svg';
import DataSvg from './data.svg';
import NotebookSvg from './notebook.svg';
import PrinterSvg from './printer.svg';
import RiceSvg from './rice.svg';
import SuitcaseSvg from './suitcase.svg';
import TruckSvg from './truck.svg';
import VoiceSvg from './voice.svg';
const ImgSvg = ({ svg }: { svg: string }) => {
return <img src={svg} width="40px" height="40px" style={{ paddingRight: '1rem' }} />;
};
const ImgCouponSvg = () => <ImgSvg svg={CouponSvg} />;
const ImgDataSvg = () => <ImgSvg svg={DataSvg} />;
const ImgNotebookSvg = () => <ImgSvg svg={NotebookSvg} />;
const ImgPrinterSvg = () => <ImgSvg svg={PrinterSvg} />;
const ImgRiceSvg = () => <ImgSvg svg={RiceSvg} />;
const ImgSuitcaseSvg = () => <ImgSvg svg={SuitcaseSvg} />;
const ImgTruckSvg = () => <ImgSvg svg={TruckSvg} />;
const ImgVoiceSvg = () => <ImgSvg svg={VoiceSvg} />;
export {
ImgCouponSvg,
ImgDataSvg,
ImgNotebookSvg,
ImgPrinterSvg,
ImgRiceSvg,
ImgSuitcaseSvg,
ImgTruckSvg,
ImgVoiceSvg,
};

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M0 0.008h1024v1023.984H0z" fill="#F4F4F4" /><path d="M978.84 907.376a69.976 69.976 0 0 1-69.968 69.96h-789.52a69.976 69.976 0 0 1-69.968-69.96V210.408a69.984 69.984 0 0 1 69.968-69.968h789.52a69.984 69.984 0 0 1 69.968 69.968v696.968z" fill="#F4A417" /><path d="M49.384 270.616v636.76a69.976 69.976 0 0 0 69.968 69.96h458.392c76.84-184.088 280.688-706.72 280.688-706.72H49.384z" fill="#F4A417" /><path d="M49.384 305.304V210.408a69.984 69.984 0 0 1 69.968-69.968h789.52a69.984 69.984 0 0 1 69.968 69.968v94.896H49.384z" fill="#E37F19" /><path d="M362.12 281.64a60.208 60.208 0 0 1-60.208-60.2V60.216a60.216 60.216 0 0 1 120.416 0v161.216a60.216 60.216 0 0 1-60.208 60.208zM666.112 281.64a60.232 60.232 0 0 1-60.208-60.2V60.216A60.24 60.24 0 0 1 666.112 0.008c33.28 0 60.2 26.96 60.2 60.208v161.216a60.184 60.184 0 0 1-60.2 60.208z" fill="#E5226B" /><path d="M362.12 0.008a60.216 60.216 0 0 1 60.208 60.208v161.216a60.208 60.208 0 0 1-60.208 60.2M666.112 0.008c33.28 0 60.2 26.96 60.2 60.208v161.216a60.176 60.176 0 0 1-60.2 60.2" fill="#C8246D" /><path d="M782.52 480.928H221.864a30.08 30.08 0 0 1-30.104-30.104 30.08 30.08 0 0 1 30.104-30.104h560.664a30.08 30.08 0 0 1 30.104 30.104 30.096 30.096 0 0 1-30.112 30.104zM507.904 672.832H221.864c-16.64 0-30.104-13.464-30.104-30.104s13.464-30.112 30.104-30.112h286.04c16.64 0 30.104 13.472 30.104 30.112s-13.464 30.104-30.104 30.104z" fill="#D98D1B" /></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M254.832 410.496V84.984h514.336v325.512" fill="#0085BF" /><path d="M254.832 281.304v-196.32h514.336v196.32" fill="#0092D2" /><path d="M242.752 841.2H105.688C51.696 841.2 8 797.416 8 743.512V500.096c0-53.936 43.696-97.72 97.688-97.72h812.616c53.968 0 97.696 43.792 97.696 97.72v243.416c0 53.896-43.728 97.688-97.696 97.688H783.608" fill="#F5B146" /><path d="M8 532.256v211.256c0 53.896 43.696 97.688 97.688 97.688h812.616c53.968 0 97.696-43.792 97.696-97.688V532.256" fill="#EDA02F" /><path d="M254.832 718.288h514.328v219.368H254.832z" fill="#E5226B" /><path d="M254.832 862.832h514.328v76.192H254.832z" fill="#C9005B" /></svg>

After

Width:  |  Height:  |  Size: 879 B

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M991.608 398.368c0-80.704-65.44-146.144-146.144-146.144l-0.68 0.712c0-80.736-65.472-146.144-146.144-146.144l-2.44-2.92C665.816 52.112 596.352 16 515.552 16c-70.176 0-131.848 27.376-166.76 68.52a139.856 139.856 0 0 0-14.936 21.336l-1.272 0.944c-80.696 0-146.144 65.408-146.144 146.144l-0.024-0.72c-80.704 0-146.144 65.44-146.144 146.144" fill="#FFC033" /><path d="M991.608 398.368c0-57.088-65.44-103.336-146.144-103.336l-0.68 0.52c0-57.128-65.472-103.336-146.144-103.336l-2.44-2.08c-30.4-36.6-99.856-62.16-180.664-62.16-70.176 0-131.848 19.352-166.76 48.456-5.712 4.776-10.72 9.84-14.936 15.104l-1.272 0.68c-80.696 0-146.144 46.216-146.144 103.336L186.416 295.032c-80.704 0-146.144 46.248-146.144 103.336" fill="#FFA836" /><path d="M728.944 869.432V1008H299.88v-138.568" fill="#0092D2" /><path d="M1028.832 391.968c0 238.08-137.696 513.704-514.416 513.704-398.48 0-514.416-275.624-514.416-513.704h1028.832z" fill="#E5297F" /><path d="M510.128 905.48c1.496 0.032 2.792 0.192 4.288 0.192 376.72 0 514.416-275.624 514.416-513.704H510.128v513.512z" fill="#D3296E" /><path d="M798.84 391.968c0 238.08-76.128 513.704-284.424 513.704-220.32 0-284.424-275.624-284.424-513.704h568.848z" fill="#F73786" /><path d="M798.84 391.968H510.128v513.344c1.496 0.032 2.792 0.36 4.288 0.36 208.296 0 284.424-275.624 284.424-513.704z" fill="#E01E88" /></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M455.176 531.168V183.936h140.608v347.232h129.304v-387.2c0-49.248-40.056-89.344-89.296-89.344H415.176c-49.248 0-89.312 40.096-89.312 89.344v387.192h129.312z" fill="#E5226B" /><path d="M1016 876.376c0 50.888-41.224 92.112-92.056 92.112H100.12C49.224 968.488 8 927.264 8 876.376V374.424c0-50.888 41.224-92.12 92.12-92.12h823.832c50.832 0 92.056 41.232 92.056 92.12v501.952z" fill="#F5B146" /><path d="M342.064 968.488H100.12C49.224 968.488 8 927.264 8 876.376V374.424c0-50.888 41.224-92.12 92.12-92.12h791.504l-549.56 686.184z" fill="#FFC83E" /><path d="M762.824 283.216h64.648v686.16h-64.648zM201.96 283.216h64.656v686.16h-64.656z" fill="#0092D2" /><path d="M234.288 283.216h32.328v686.16h-32.328zM795.144 283.216h32.328v686.16h-32.328z" fill="#0085BF" /></svg>

After

Width:  |  Height:  |  Size: 1011 B

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M425.176 123.4h554.432v424.992H425.176z" fill="#E6246B" /><path d="M893.832 809.152c47.384 0 85.784-38.392 85.784-85.784V543.624H425.976V241.288l-234.064-0.768L40.92 492.192V723.36c0 47.392 38.392 85.784 85.752 85.784h767.16z" fill="#F6B246" /><path d="M893.832 809.152c47.384 0 85.784-38.392 85.784-85.784V603.832H40.92V723.36c0 47.392 38.392 85.784 85.752 85.784h767.16z" fill="#ECD4BE" /><path d="M853.728 824.552c0 56.152-45.504 101.592-101.6 101.592-56.152 0-101.592-45.448-101.592-101.592 0-56.096 45.448-101.6 101.592-101.6 56.088 0 101.6 45.512 101.6 101.6zM379.584 824.552c0 56.152-45.48 101.592-101.6 101.592s-101.6-45.448-101.6-101.592c0-56.096 45.48-101.6 101.6-101.6s101.6 45.512 101.6 101.6z" fill="#0093D3" /><path d="M264.192 454.568H62.848l109.128-178.736h92.216z" fill="#E09431" /></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M261.84 693.464V286.064c0-131.496 106.592-238.128 238.12-238.128 131.552 0 238.16 106.632 238.16 238.128l0.76 407.392S619.496 786.472 500.32 784.696c-125.416-1.84-238.48-91.232-238.48-91.232z" fill="#F0AF2D" /><path d="M261.84 694.048c-119.032 0-215.368-78.816-215.368-206.896 0-134.936 96.336-206.96 215.368-206.96v413.856z" fill="#0092D2" /><path d="M738.872 693.464l-0.76-407.392c0-3.616-0.384-7.112-0.536-10.696L261.84 648.512v44.944s113.064 89.4 238.472 91.24c119.184 1.784 238.56-91.232 238.56-91.232z" fill="#EEA03A" /><path d="M955.944 485.616c0-143.696-97.128-208.576-217.072-208.576v397.448l-92.456 218.248a30.128 30.128 0 0 0 27.72 41.84c11.696 0 22.864-6.88 27.728-18.376l97.04-229.04c90.664-21.392 157.04-92.304 157.04-201.544z" fill="#1A8DCC" /><path d="M549.224 1001.096a60.272 60.272 0 0 1-56.44-39.232 60.24 60.24 0 0 1 35.456-77.432l107.976-40.168c31.168-11.52 65.832 4.296 77.44 35.464a60.264 60.264 0 0 1-35.456 77.432l-107.976 40.16a60.832 60.832 0 0 1-21 3.776z" fill="#E5226B" /></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -18,39 +18,39 @@
* https://ionicframework.com/docs/theming/colors#new-color-creator
*/
:root {
:root {
--ion-color-favorite: #69bb7b;
--ion-color-favorite-rgb: 105,187,123;
--ion-color-favorite-rgb: 105, 187, 123;
--ion-color-favorite-contrast: #ffffff;
--ion-color-favorite-contrast-rgb: 255,255,255;
--ion-color-favorite-contrast-rgb: 255, 255, 255;
--ion-color-favorite-shade: #5ca56c;
--ion-color-favorite-tint: #78c288;
--ion-color-twitter: #1da1f4;
--ion-color-twitter-rgb: 29,161,244;
--ion-color-twitter-rgb: 29, 161, 244;
--ion-color-twitter-contrast: #ffffff;
--ion-color-twitter-contrast-rgb: 255,255,255;
--ion-color-twitter-contrast-rgb: 255, 255, 255;
--ion-color-twitter-shade: #1a8ed7;
--ion-color-twitter-tint: #34aaf5;
--ion-color-instagram: #5956d8;
--ion-color-instagram-rgb: 89,86,216;
--ion-color-instagram-rgb: 89, 86, 216;
--ion-color-instagram-contrast: #ffffff;
--ion-color-instagram-contrast-rgb: 255,255,255;
--ion-color-instagram-contrast-rgb: 255, 255, 255;
--ion-color-instagram-shade: #4e4cbe;
--ion-color-instagram-tint: #6a67dc;
--ion-color-vimeo: #23b6ea;
--ion-color-vimeo-rgb: 35,182,234;
--ion-color-vimeo-rgb: 35, 182, 234;
--ion-color-vimeo-contrast: #ffffff;
--ion-color-vimeo-contrast-rgb: 255,255,255;
--ion-color-vimeo-contrast-rgb: 255, 255, 255;
--ion-color-vimeo-shade: #1fa0ce;
--ion-color-vimeo-tint: #39bdec;
--ion-color-facebook: #3b5998;
--ion-color-facebook-rgb: 59,89,152;
--ion-color-facebook-rgb: 59, 89, 152;
--ion-color-facebook-contrast: #ffffff;
--ion-color-facebook-contrast-rgb: 255,255,255;
--ion-color-facebook-contrast-rgb: 255, 255, 255;
--ion-color-facebook-shade: #344e86;
--ion-color-facebook-tint: #4f6aa2;
}
@@ -110,19 +110,19 @@
}
.ion-color-github {
--ion-color-base: #211F1F;
--ion-color-base-rgb: 33,31,31;
--ion-color-base: #211f1f;
--ion-color-base-rgb: 33, 31, 31;
--ion-color-contrast: #ffffff;
--ion-color-contrast-rgb: 255,255,255;
--ion-color-contrast-rgb: 255, 255, 255;
--ion-color-shade: #1d1b1b;
--ion-color-tint: #373535;
}
.ion-color-instagram {
--ion-color-base: #9537BC;
--ion-color-base-rgb: 149,55,188;
--ion-color-base: #9537bc;
--ion-color-base-rgb: 149, 55, 188;
--ion-color-contrast: #ffffff;
--ion-color-contrast-rgb: 255,255,255;
--ion-color-contrast-rgb: 255, 255, 255;
--ion-color-shade: #8330a5;
--ion-color-tint: #a04bc3;
}
@@ -157,7 +157,6 @@
*/
.ios {
}
/*
@@ -167,5 +166,4 @@
*/
.md {
}