first
This commit is contained in:
79
src/pages/ComingSoon.tsx
Normal file
79
src/pages/ComingSoon.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { Col, Form, Row } from 'react-bootstrap';
|
||||
import Lottie from 'lottie-react';
|
||||
import comingSoonLight from 'assets/img/animated-icons/coming-soon-light.json';
|
||||
import comingSoonDark from 'assets/img/animated-icons/coming-soon-dark.json';
|
||||
import comingSoonText from 'assets/img/spot-illustrations/40.png';
|
||||
import comingSoonTextDark from 'assets/img/spot-illustrations/dark_40.png';
|
||||
import { useAppContext } from 'providers/AppProvider';
|
||||
import Button from 'components/base/Button';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faEnvelope } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
const ComingSoon = () => {
|
||||
const {
|
||||
config: { theme }
|
||||
} = useAppContext();
|
||||
|
||||
return (
|
||||
<Row className="flex-center content-min-h pb-9">
|
||||
<Col xs={12} xxl={10}>
|
||||
<Row className="align-items-xl-center g-2">
|
||||
<Col xs={12} xl={6} className="order-xl-1">
|
||||
<div className="d-flex flex-center">
|
||||
<Lottie
|
||||
animationData={
|
||||
theme === 'light' ? comingSoonLight : comingSoonDark
|
||||
}
|
||||
loop={true}
|
||||
className="w-xl-100 animation"
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
<Col xs={12} xl={6}>
|
||||
<div className="d-flex justify-content-center mt-xl-15">
|
||||
<div className="text-container text-center text-xl-start">
|
||||
<img
|
||||
src={comingSoonText}
|
||||
alt=""
|
||||
className="mb-5 w-75 w-lg-50 w-xl-75 w-xxl-100 d-dark-none"
|
||||
style={{ maxWidth: 415 }}
|
||||
/>
|
||||
<img
|
||||
src={comingSoonTextDark}
|
||||
alt=""
|
||||
className="mb-5 w-75 w-lg-50 w-xl-75 w-xxl-100 d-light-none"
|
||||
style={{ maxWidth: 415 }}
|
||||
/>
|
||||
|
||||
<h2 className="text-body-secondary fs-xl-6 mb-3">
|
||||
Get notified when we launch
|
||||
</h2>
|
||||
<p className="mb-6 w-xxl-75">
|
||||
<b>Something in the way!</b> Subscribe to our newsletter to be
|
||||
the first to know about upcoming features and discounts.
|
||||
</p>
|
||||
<Row className="g-3 w-md-75 w-xl-100 w-xxl-75 mx-auto mx-xl-0">
|
||||
<Col className="ps-0">
|
||||
<Form.Control />
|
||||
</Col>
|
||||
<Col xs="auto" className="pe-0">
|
||||
<Button
|
||||
variant="primary"
|
||||
endIcon={
|
||||
<FontAwesomeIcon icon={faEnvelope} className="fs-10" />
|
||||
}
|
||||
>
|
||||
Subscribe
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
export default ComingSoon;
|
||||
70
src/pages/Members.tsx
Normal file
70
src/pages/Members.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import SearchBox from 'components/common/SearchBox';
|
||||
import useAdvanceTable from 'hooks/useAdvanceTable';
|
||||
import AdvanceTableProvider from 'providers/AdvanceTableProvider';
|
||||
import { ChangeEvent } from 'react';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { memberBreadcrumbItems, members } from 'data/members';
|
||||
import MembersTable, {
|
||||
membersTablecolumns
|
||||
} from 'components/tables/MembersTable';
|
||||
import { faFileExport, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
const Members = () => {
|
||||
const table = useAdvanceTable({
|
||||
data: members,
|
||||
columns: membersTablecolumns,
|
||||
pageSize: 10,
|
||||
pagination: true,
|
||||
sortable: true,
|
||||
selection: true
|
||||
});
|
||||
|
||||
const handleSearchInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
table.setGlobalFilter(e.target.value || undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={memberBreadcrumbItems} />
|
||||
<div className="mb-9">
|
||||
<h2 className="mb-5">Members</h2>
|
||||
|
||||
<AdvanceTableProvider {...table}>
|
||||
<div className="mb-4">
|
||||
<Row className="g-3">
|
||||
<Col xs="auto">
|
||||
<SearchBox
|
||||
placeholder="Search members"
|
||||
onChange={handleSearchInputChange}
|
||||
/>
|
||||
</Col>
|
||||
<Col
|
||||
xs="auto"
|
||||
className="scrollbar overflow-hidden-y flex-grow-1"
|
||||
></Col>
|
||||
<Col xs="auto">
|
||||
<Button variant="link" className="text-body me-4 px-0">
|
||||
<FontAwesomeIcon icon={faFileExport} className="fs-9 me-2" />
|
||||
Export
|
||||
</Button>
|
||||
<Button variant="primary">
|
||||
<FontAwesomeIcon icon={faPlus} className="me-2" />
|
||||
Add member
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis border-top border-bottom border-translucent position-relative top-1">
|
||||
<MembersTable />
|
||||
</div>
|
||||
</AdvanceTableProvider>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Members;
|
||||
63
src/pages/Showcase.tsx
Normal file
63
src/pages/Showcase.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import Footer from 'components/footers/Footer';
|
||||
import AdvanceFeatures from 'components/modules/showcase/AdvanceFeatures';
|
||||
import Cta from 'components/modules/showcase/Cta';
|
||||
import Demos from 'components/modules/showcase/Demos';
|
||||
import DifferentModules from 'components/modules/showcase/DifferentModules';
|
||||
import EssentialFeatures from 'components/modules/showcase/EssentialFeatures';
|
||||
import Faq from 'components/modules/showcase/Faq';
|
||||
import Feature from 'components/modules/showcase/Feature';
|
||||
import FeatureFigma from 'components/modules/showcase/FeatureFigma';
|
||||
import Header from 'components/modules/showcase/Header';
|
||||
import ImportantApplications from 'components/modules/showcase/ImportantApplications';
|
||||
import NecessaryPages from 'components/modules/showcase/NecessaryPages';
|
||||
import PreFooter from 'components/modules/showcase/PreFooter';
|
||||
import ShowcaseNavbar from 'components/navbars/ShowcaseNavbar';
|
||||
import useSettingsMountEffect from 'hooks/useSettingsMountEffect';
|
||||
import { useAppContext } from 'providers/AppProvider';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
|
||||
const Showcase = () => {
|
||||
useSettingsMountEffect({
|
||||
showSettingPanelButton: false
|
||||
});
|
||||
const {
|
||||
config: { theme },
|
||||
setConfig
|
||||
} = useAppContext();
|
||||
|
||||
const mountTheme = useMemo(() => {
|
||||
return theme;
|
||||
}, [theme]);
|
||||
|
||||
useEffect(() => {
|
||||
setConfig({
|
||||
theme: 'light'
|
||||
});
|
||||
return () => {
|
||||
setConfig({
|
||||
theme: mountTheme
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ShowcaseNavbar />
|
||||
<Header />
|
||||
<Demos />
|
||||
<DifferentModules />
|
||||
<AdvanceFeatures />
|
||||
<EssentialFeatures />
|
||||
<Feature />
|
||||
<ImportantApplications />
|
||||
<NecessaryPages />
|
||||
<FeatureFigma />
|
||||
<Faq />
|
||||
<Cta />
|
||||
<PreFooter />
|
||||
<Footer className="d-flex justify-content-center bg-body border-0" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Showcase;
|
||||
61
src/pages/apps/calendar/Calendar.tsx
Normal file
61
src/pages/apps/calendar/Calendar.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { EventClickArg } from '@fullcalendar/core';
|
||||
import CalendarAddNewEventModal from 'components/modals/CalendarAddNewEventModal';
|
||||
import CalendarProvider, {
|
||||
useCalendarContext
|
||||
} from 'providers/CalendarProvider';
|
||||
import CalendarTop from './CalendarTop';
|
||||
import CalendarHeader from './CalendarHeader';
|
||||
import CalendarEventModal from 'components/modals/CalendarEventModal';
|
||||
import { HANDLE_SELECT, SET_CALENDAR_STATE } from 'reducers/CalendarReducer';
|
||||
import FullCalendar from 'components/base/FullCalendar';
|
||||
import events from 'data/calendarEvents';
|
||||
|
||||
const index = () => {
|
||||
return (
|
||||
<CalendarProvider>
|
||||
<Calendar />
|
||||
</CalendarProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const Calendar = () => {
|
||||
const { calendarDispatch } = useCalendarContext();
|
||||
|
||||
const handleEventClick = (info: EventClickArg) => {
|
||||
if (info.event.url) {
|
||||
window.open(info.event.url);
|
||||
info.jsEvent.preventDefault();
|
||||
} else {
|
||||
calendarDispatch({
|
||||
type: SET_CALENDAR_STATE,
|
||||
payload: {
|
||||
selectedEvent: info.event
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CalendarTop />
|
||||
<CalendarHeader />
|
||||
<div className="mt-6 mb-9">
|
||||
<FullCalendar
|
||||
height={800}
|
||||
select={info => {
|
||||
calendarDispatch({
|
||||
type: HANDLE_SELECT,
|
||||
payload: info
|
||||
});
|
||||
}}
|
||||
events={events}
|
||||
eventClick={handleEventClick}
|
||||
/>
|
||||
</div>
|
||||
<CalendarEventModal />
|
||||
<CalendarAddNewEventModal />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default index;
|
||||
107
src/pages/apps/calendar/CalendarHeader.tsx
Normal file
107
src/pages/apps/calendar/CalendarHeader.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import {
|
||||
faChevronLeft,
|
||||
faChevronRight
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import classNames from 'classnames';
|
||||
import Button from 'components/base/Button';
|
||||
import { CalendarView, useCalendarContext } from 'providers/CalendarProvider';
|
||||
import { ButtonGroup, Col, Row } from 'react-bootstrap';
|
||||
import { SET_CALENDAR_STATE } from 'reducers/CalendarReducer';
|
||||
|
||||
const CalendarHeader = () => {
|
||||
const { calendarApi, title, view, calendarDispatch } = useCalendarContext();
|
||||
|
||||
const handleCalendarView = (viewType: CalendarView) => {
|
||||
if (calendarApi) {
|
||||
calendarApi.changeView(viewType);
|
||||
calendarDispatch({
|
||||
type: SET_CALENDAR_STATE,
|
||||
payload: {
|
||||
view: viewType,
|
||||
title: calendarApi.view.title
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleCalendarUpdate = (actionType: string) => {
|
||||
if (calendarApi) {
|
||||
actionType === 'next'
|
||||
? calendarApi.next()
|
||||
: actionType === 'prev'
|
||||
? calendarApi.prev()
|
||||
: calendarApi.today();
|
||||
calendarDispatch({
|
||||
type: SET_CALENDAR_STATE,
|
||||
payload: {
|
||||
title: calendarApi.view.title
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 border-y border-translucent">
|
||||
<Row className="py-3 gy-3 gx-0 justify-content-between">
|
||||
<Col xs={6} md="auto" className="order-1 d-flex align-items-center">
|
||||
<Button
|
||||
onClick={() => handleCalendarUpdate('today')}
|
||||
variant="phoenix-primary"
|
||||
size="sm"
|
||||
className="px-4"
|
||||
>
|
||||
Today
|
||||
</Button>
|
||||
</Col>
|
||||
<Col
|
||||
xs={12}
|
||||
md="auto"
|
||||
className="order-md-1 d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<Button
|
||||
onClick={() => handleCalendarUpdate('prev')}
|
||||
className="icon-item icon-item-sm shadow-none text-body-emphasis p-0"
|
||||
>
|
||||
<FontAwesomeIcon icon={faChevronLeft} />
|
||||
</Button>
|
||||
{calendarApi && (
|
||||
<h3 className="px-3 text-body-emphasis fw-semibold mb-0">
|
||||
{title || calendarApi.view.title}
|
||||
</h3>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => handleCalendarUpdate('next')}
|
||||
className="icon-item icon-item-sm shadow-none text-body-emphasis p-0"
|
||||
>
|
||||
<FontAwesomeIcon icon={faChevronRight} />
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs={6} md="auto" className="order-1 d-flex justify-content-end">
|
||||
<ButtonGroup size="sm">
|
||||
<Button
|
||||
onClick={() => handleCalendarView('dayGridMonth')}
|
||||
variant="phoenix-secondary"
|
||||
className={classNames({
|
||||
active: view === 'dayGridMonth'
|
||||
})}
|
||||
>
|
||||
Month
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => handleCalendarView('timeGridWeek')}
|
||||
variant="phoenix-secondary"
|
||||
className={classNames({
|
||||
active: view === 'timeGridWeek'
|
||||
})}
|
||||
>
|
||||
Week
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CalendarHeader;
|
||||
54
src/pages/apps/calendar/CalendarTop.tsx
Normal file
54
src/pages/apps/calendar/CalendarTop.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { faPlus, faSync } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import dayjs from 'dayjs';
|
||||
import { useCalendarContext } from 'providers/CalendarProvider';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { SET_CALENDAR_STATE } from 'reducers/CalendarReducer';
|
||||
|
||||
const CalendarTop = () => {
|
||||
const { calendarDispatch } = useCalendarContext();
|
||||
|
||||
return (
|
||||
<Row className="g-0 mb-4 align-items-center">
|
||||
<Col xs={5} md={6}>
|
||||
<h4 className="mb-0 text-body-emphasis fw-bold fs-md-6">
|
||||
<span className="calendar-day d-block d-md-inline mb-1">
|
||||
{dayjs().format('dddd')}
|
||||
</span>
|
||||
<span className="px-3 fw-thin text-body-quaternary d-none d-md-inline">
|
||||
|
|
||||
</span>
|
||||
<span className="d-inline-block">
|
||||
{' '}
|
||||
{dayjs().format('D MMM, YYYY')}
|
||||
</span>
|
||||
</h4>
|
||||
</Col>
|
||||
<Col xs={7} md={6} className="d-flex justify-content-end">
|
||||
<Button
|
||||
variant="link"
|
||||
className="text-body px-0 me-2 me-md-4"
|
||||
startIcon={<FontAwesomeIcon icon={faSync} className="fs-10 me-2" />}
|
||||
>
|
||||
<span className="d-none d-md-inline">Sync Now</span>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
calendarDispatch({
|
||||
type: SET_CALENDAR_STATE,
|
||||
payload: { openNewEventModal: true }
|
||||
});
|
||||
}}
|
||||
variant="primary"
|
||||
size="sm"
|
||||
startIcon={<FontAwesomeIcon icon={faPlus} className="fs-10 me-2" />}
|
||||
>
|
||||
Add new task
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
export default CalendarTop;
|
||||
15
src/pages/apps/chat/Chat.tsx
Normal file
15
src/pages/apps/chat/Chat.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { conversations } from 'data/chat';
|
||||
import ChatProvider from 'providers/ChatProvider';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
|
||||
const Chat = () => {
|
||||
return (
|
||||
<ChatProvider conversations={conversations}>
|
||||
<div className="chat d-flex gap-3">
|
||||
<Outlet />
|
||||
</div>
|
||||
</ChatProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Chat;
|
||||
32
src/pages/apps/chat/ChatConversation.tsx
Normal file
32
src/pages/apps/chat/ChatConversation.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import ChatContent from 'components/modules/chat/chat-content';
|
||||
import ChatSidebar from 'components/modules/chat/ChatSidebar';
|
||||
import { useBreakpoints } from 'providers/BreakpointsProvider';
|
||||
import { useChatContext } from 'providers/ChatProvider';
|
||||
import { useEffect } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { SET_CURRENT_CONVERSATION } from 'reducers/ChatReducer';
|
||||
|
||||
const ChatConversation = () => {
|
||||
const { userId } = useParams();
|
||||
|
||||
const { chatDispatch, conversations } = useChatContext();
|
||||
|
||||
const { breakpoints } = useBreakpoints();
|
||||
useEffect(() => {
|
||||
chatDispatch({
|
||||
type: SET_CURRENT_CONVERSATION,
|
||||
payload: {
|
||||
userId
|
||||
}
|
||||
});
|
||||
}, [userId, conversations]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{breakpoints.up('sm') && <ChatSidebar />}
|
||||
<ChatContent />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChatConversation;
|
||||
13
src/pages/apps/chat/ChatHomepage.tsx
Normal file
13
src/pages/apps/chat/ChatHomepage.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import ChatHomepageCard from 'components/cards/ChatHomepageCard';
|
||||
import ChatSidebar from 'components/modules/chat/ChatSidebar';
|
||||
|
||||
const ChatHomepage = () => {
|
||||
return (
|
||||
<>
|
||||
<ChatSidebar />
|
||||
<ChatHomepageCard />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChatHomepage;
|
||||
61
src/pages/apps/crm/AddContact.tsx
Normal file
61
src/pages/apps/crm/AddContact.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import Button from 'components/base/Button';
|
||||
import AvatarUpload from 'components/common/AvatarUpload';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import avatar from 'assets/img/team/150x150/58.webp';
|
||||
import { Col, FloatingLabel, Form, Row } from 'react-bootstrap';
|
||||
import LeadInformationForm from 'components/forms/LeadInformationForm';
|
||||
import AddressInformation from 'components/forms/AddressInformation';
|
||||
|
||||
const AddContact = () => {
|
||||
return (
|
||||
<div className="mb-9">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="border-bottom border-translucent mb-7 mx-n3 px-2 mx-lg-n6 px-lg-6">
|
||||
<Row>
|
||||
<Col xl={9}>
|
||||
<div className="d-sm-flex justify-content-between">
|
||||
<h2 className="mb-4">Create a new lead</h2>
|
||||
<div className="d-flex mb-3">
|
||||
<Button variant="phoenix-primary" className="me-2 px-6">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="primary">Create lead</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<Row>
|
||||
<Col xl={9}>
|
||||
<div className="d-flex align-items-end position-relative mb-7">
|
||||
<AvatarUpload src={avatar} size="5xl" />
|
||||
</div>
|
||||
<Form>
|
||||
<LeadInformationForm className="mb-6" />
|
||||
<AddressInformation className="mb-6" />
|
||||
<h4 className="mb-3">Description</h4>
|
||||
<FloatingLabel
|
||||
controlId="lead-description"
|
||||
label="Lead description"
|
||||
>
|
||||
<Form.Control
|
||||
as="textarea"
|
||||
style={{ height: '128px' }}
|
||||
type="text"
|
||||
placeholder="Lead description"
|
||||
/>
|
||||
</FloatingLabel>
|
||||
<div className="text-end">
|
||||
<Button variant="primary" className="mt-6">
|
||||
Create lead
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddContact;
|
||||
56
src/pages/apps/crm/Analytics.tsx
Normal file
56
src/pages/apps/crm/Analytics.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import DatePicker from 'components/base/DatePicker';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import CallCampaignReport from 'components/modules/crm/analytics/CallCampaignReport';
|
||||
import EmailCampaign from 'components/modules/crm/analytics/EmailCampaign';
|
||||
import MarketingCampaign from 'components/modules/crm/analytics/MarketingCampaign';
|
||||
import SalesTrends from 'components/modules/crm/analytics/SalesTrends';
|
||||
import AnalyticsStats from 'components/stats/AnalyticsStats';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { stats } from 'data/crm/stats';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
|
||||
const Analytics = () => {
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-6">
|
||||
<Row className="align-items-center justify-content-between g-3 mb-6">
|
||||
<Col md="auto">
|
||||
<h2 className="mb-0">Analytics</h2>
|
||||
</Col>
|
||||
<Col md="auto">
|
||||
<DatePicker defaultValue="Mar 1, 2022" />
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="px-3 mb-6">
|
||||
<AnalyticsStats stats={stats} />
|
||||
</div>
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis pt-6 pb-3 border-y">
|
||||
<Row className="gx-6">
|
||||
<Col
|
||||
md={6}
|
||||
lg={12}
|
||||
xl={6}
|
||||
className="mb-5 mb-md-3 mb-lg-5 mb-xl-2 mb-xxl-3"
|
||||
>
|
||||
<EmailCampaign />
|
||||
</Col>
|
||||
<Col md={6} lg={12} xl={6} className="mb-1 mb-sm-0">
|
||||
<MarketingCampaign />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<Row className="pt-6 gy-7 gx-6">
|
||||
<Col md={6}>
|
||||
<SalesTrends />
|
||||
</Col>
|
||||
<Col md={6}>
|
||||
<CallCampaignReport />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Analytics;
|
||||
72
src/pages/apps/crm/DealDetails.tsx
Normal file
72
src/pages/apps/crm/DealDetails.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import { faEdit, faEllipsis, faTrash } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import DealProfileCard from 'components/cards/DealProfileCard';
|
||||
import DealsPrintingDimensionsCard from 'components/cards/DealsPrintingDimensionsCard';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import DealsOtherInformation from 'components/forms/DealsOtherInformation';
|
||||
import DealDetailsInfo from 'components/modules/crm/deals-details/DealDetailsInfo';
|
||||
import DealDetailsTab from 'components/modules/crm/deals-details/DealDetailsTab';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { dealDetailsInfoData, stats } from 'data/crm/dealDetailsInfo';
|
||||
import { Col, Dropdown, Row } from 'react-bootstrap';
|
||||
|
||||
const DealDetails = () => {
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-9">
|
||||
<Row className="align-items-center justify-content-between g-3 mb-4">
|
||||
<Col md="auto">
|
||||
<h2 className="mb-0">Deal details</h2>
|
||||
</Col>
|
||||
<Col md="auto" className="d-flex">
|
||||
<Button variant="phoenix-secondary" className="px-3 px-sm-5 me-2">
|
||||
<FontAwesomeIcon icon={faEdit} className="me-sm-2" />
|
||||
<span className="d-none d-sm-inline">Edit</span>
|
||||
</Button>
|
||||
<Button
|
||||
variant="phoenix-danger"
|
||||
className="me-2"
|
||||
startIcon={<FontAwesomeIcon icon={faTrash} className="me-2" />}
|
||||
>
|
||||
<span>Delete Deal</span>
|
||||
</Button>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
variant="phoenix-secondary"
|
||||
className="px-3 dropdown-caret-none"
|
||||
>
|
||||
<FontAwesomeIcon icon={faEllipsis} />
|
||||
</Dropdown.Toggle>
|
||||
|
||||
<Dropdown.Menu className="py-2" style={{ zIndex: 9999 }}>
|
||||
<Dropdown.Item href="#!">View profile</Dropdown.Item>
|
||||
<Dropdown.Item href="#!">Report</Dropdown.Item>
|
||||
<Dropdown.Item href="#!">Manage notifications</Dropdown.Item>
|
||||
<Dropdown.Item href="#!" className="text-danger">
|
||||
Delete Lead
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="g-4 g-xl-6">
|
||||
<Col xl={5} xxl={4}>
|
||||
<div className="sticky-leads-sidebar">
|
||||
<DealProfileCard className="mb-3" />
|
||||
<DealsOtherInformation />
|
||||
</div>
|
||||
</Col>
|
||||
<Col xl={7} xxl={8}>
|
||||
<DealsPrintingDimensionsCard stats={stats} className="mb-5" />
|
||||
<DealDetailsInfo data={dealDetailsInfoData} className="mb-7" />
|
||||
<DealDetailsTab />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DealDetails;
|
||||
157
src/pages/apps/crm/Deals.tsx
Normal file
157
src/pages/apps/crm/Deals.tsx
Normal file
@@ -0,0 +1,157 @@
|
||||
import {
|
||||
faFileExport,
|
||||
faFilter,
|
||||
faPlus
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import SearchBox from 'components/common/SearchBox';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { dealColumnsData } from 'data/crm/deals';
|
||||
import { useEffect } from 'react';
|
||||
import { Col, Form, Row } from 'react-bootstrap';
|
||||
import { useMainLayoutContext } from 'providers/MainLayoutProvider';
|
||||
import DealColumn from 'components/modules/crm/deals/DealColumn';
|
||||
import AddDealModal from 'components/modules/crm/deals/AddDealModal';
|
||||
import FilterDealsModal from 'components/modals/FilterDealsModal';
|
||||
import DealsAddStageModal from 'components/modals/DealsAddStageModal';
|
||||
import DealsProvider, { useDealsContext } from 'providers/CrmDealsProvider';
|
||||
import { DndContext, closestCorners, DragOverlay } from '@dnd-kit/core';
|
||||
import DealCard from 'components/cards/DealCard';
|
||||
import { useGetDndSensor } from 'hooks/useGetDndSensor';
|
||||
|
||||
const index = () => {
|
||||
return (
|
||||
<DealsProvider data={dealColumnsData}>
|
||||
<Deals />
|
||||
</DealsProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const Deals = () => {
|
||||
const { setContentClass } = useMainLayoutContext();
|
||||
const {
|
||||
dealColumns,
|
||||
openAddDealModal,
|
||||
setOpenAddDealModal,
|
||||
openFilterDealModal,
|
||||
setOpenFilterDealModal,
|
||||
openAddStageModal,
|
||||
setOpenAddStageModal,
|
||||
activeDeal,
|
||||
activeColumnId,
|
||||
handleDragStart,
|
||||
handleDragOver,
|
||||
handleDragEnd
|
||||
} = useDealsContext();
|
||||
const sensors = useGetDndSensor();
|
||||
useEffect(() => {
|
||||
setContentClass('vh-100');
|
||||
|
||||
return () => {
|
||||
setContentClass('');
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="d-flex flex-column h-100">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-6">
|
||||
<h2 className="mb-5">Deals</h2>
|
||||
<Row className="g-3 justify-content-between">
|
||||
<Col xs="auto">
|
||||
<Button
|
||||
variant="primary"
|
||||
className="me-4"
|
||||
startIcon={<FontAwesomeIcon icon={faPlus} className="me-2" />}
|
||||
onClick={() => setOpenAddDealModal(true)}
|
||||
>
|
||||
Add Deal
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
className="text-body px-0"
|
||||
startIcon={
|
||||
<FontAwesomeIcon icon={faFileExport} className="fs-9 me-2" />
|
||||
}
|
||||
>
|
||||
Export
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs="auto">
|
||||
<div className="d-flex">
|
||||
<SearchBox placeholder="Search by name" className="me-2" />
|
||||
<Form.Select className="w-auto">
|
||||
<option value="deals">Deals</option>
|
||||
</Form.Select>
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
className="px-3 ms-2"
|
||||
onClick={() => setOpenFilterDealModal(true)}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faFilter}
|
||||
transform="down-3"
|
||||
className="text-primary"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCorners}
|
||||
onDragStart={handleDragStart}
|
||||
onDragOver={handleDragOver}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 flex-1 d-flex gap-4 scrollbar">
|
||||
{dealColumns.map(col => (
|
||||
<DealColumn
|
||||
column={col}
|
||||
handleOpenAddModal={() => setOpenAddDealModal(true)}
|
||||
key={col.id}
|
||||
/>
|
||||
))}
|
||||
<div className="deals-column flex-center flex-shrink-0">
|
||||
<h3 className="mb-4">Add new stage</h3>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
startIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => setOpenAddStageModal(true)}
|
||||
>
|
||||
New Stage
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<DragOverlay>
|
||||
{activeColumnId && activeDeal && (
|
||||
<DealCard
|
||||
deal={activeDeal}
|
||||
columnId={activeColumnId}
|
||||
cursor={true}
|
||||
/>
|
||||
)}
|
||||
</DragOverlay>
|
||||
</DndContext>
|
||||
|
||||
<AddDealModal
|
||||
show={openAddDealModal}
|
||||
handleClose={() => setOpenAddDealModal(false)}
|
||||
/>
|
||||
<FilterDealsModal
|
||||
show={openFilterDealModal}
|
||||
handleClose={() => setOpenFilterDealModal(false)}
|
||||
/>
|
||||
<DealsAddStageModal
|
||||
show={openAddStageModal}
|
||||
handleClose={() => setOpenAddStageModal(false)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default index;
|
||||
135
src/pages/apps/crm/LeadDetails.tsx
Normal file
135
src/pages/apps/crm/LeadDetails.tsx
Normal file
@@ -0,0 +1,135 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import AboutLeadCard from 'components/cards/AboutLeadCard';
|
||||
import LeadAddressCard from 'components/cards/LeadAddressCard';
|
||||
import LeadProfileCard from 'components/cards/LeadProfileCard';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import LeadDeals from 'components/modules/crm/LeadDeals';
|
||||
import LeadEmails from 'components/modules/crm/LeadEmails';
|
||||
import Tasks from 'components/modules/crm/Tasks';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Col, Dropdown, Row } from 'react-bootstrap';
|
||||
import LeadAttachments from 'components/modules/crm/LeadAttachments';
|
||||
import LeadDetailsNavbar from 'components/modules/crm/LeadDetailsNavbar';
|
||||
import { useState } from 'react';
|
||||
import LeadDetailsOffcanvas from 'components/modules/crm/LeadDetailsOffcanvas';
|
||||
import {
|
||||
faBars,
|
||||
faEllipsis,
|
||||
faEnvelope,
|
||||
faThumbtack
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import ScrollSpy from 'components/base/ScrollSpy';
|
||||
|
||||
const LeadDetails = () => {
|
||||
const [openOffcanvas, setOpenOffcanvas] = useState(false);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="pb-9">
|
||||
<Row className="align-items-center justify-content-between g-3 mb-3">
|
||||
<Col xs={12} md="auto">
|
||||
<h2 className="mb-0">Lead details</h2>
|
||||
</Col>
|
||||
<Col xs={12} md="auto">
|
||||
<div className="d-flex gap-2">
|
||||
<div className="flex-1 d-md-none">
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
className="px-3 text-body-tertiary"
|
||||
onClick={() => setOpenOffcanvas(true)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faBars} />
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
variant="primary"
|
||||
startIcon={
|
||||
<FontAwesomeIcon icon={faEnvelope} className="me-2" />
|
||||
}
|
||||
>
|
||||
Send an email
|
||||
</Button>
|
||||
<Button variant="phoenix-secondary" className="px-3 px-sm-5">
|
||||
<FontAwesomeIcon icon={faThumbtack} className="me-0 me-sm-2" />
|
||||
<span className="d-none d-sm-inline">Shortlist</span>
|
||||
</Button>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
variant="phoenix-secondary"
|
||||
className="dropdown-caret-none px-3"
|
||||
>
|
||||
<FontAwesomeIcon icon={faEllipsis} />
|
||||
</Dropdown.Toggle>
|
||||
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item href="#!">View Profile</Dropdown.Item>
|
||||
<Dropdown.Item href="#!">Report</Dropdown.Item>
|
||||
<Dropdown.Item href="#!">Manage notifications</Dropdown.Item>
|
||||
<Dropdown.Item href="#!" className="text-danger">
|
||||
Delete Lead
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row className="g-0 g-md-4 g-xl-6">
|
||||
<Col md={5} xl={4} className="d-none d-md-block">
|
||||
<div className="sticky-leads-sidebar">
|
||||
<div className="lead-details-offcanvas bg-body scrollbar">
|
||||
<div className="d-flex justify-content-between align-items-center mb-2 d-md-none">
|
||||
<h3 className="mb-0">Lead Details</h3>
|
||||
</div>
|
||||
<LeadProfileCard className="mb-3" />
|
||||
<AboutLeadCard className="mb-3" />
|
||||
<LeadAddressCard />
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
<Col md={7} xl={8}>
|
||||
<div className="lead-details-container">
|
||||
<ScrollSpy>
|
||||
<LeadDetailsNavbar />
|
||||
|
||||
<ScrollSpy.Content
|
||||
id="tasks"
|
||||
className="lead-details-scrollspy mb-8"
|
||||
>
|
||||
<Tasks />
|
||||
</ScrollSpy.Content>
|
||||
|
||||
<ScrollSpy.Content
|
||||
id="deals"
|
||||
className="lead-details-scrollspy mb-8"
|
||||
minTopValue={150}
|
||||
>
|
||||
<LeadDeals />
|
||||
</ScrollSpy.Content>
|
||||
|
||||
<ScrollSpy.Content
|
||||
id="emails"
|
||||
className="lead-details-scrollspy mb-8"
|
||||
>
|
||||
<LeadEmails />
|
||||
</ScrollSpy.Content>
|
||||
|
||||
<ScrollSpy.Content
|
||||
id="attachments"
|
||||
className="lead-details-scrollspy"
|
||||
>
|
||||
<LeadAttachments />
|
||||
</ScrollSpy.Content>
|
||||
</ScrollSpy>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<LeadDetailsOffcanvas open={openOffcanvas} setOpen={setOpenOffcanvas} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LeadDetails;
|
||||
97
src/pages/apps/crm/Leads.tsx
Normal file
97
src/pages/apps/crm/Leads.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
import {
|
||||
faFileExport,
|
||||
faFilter,
|
||||
faPlus
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import DatePicker from 'components/base/DatePicker';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import SearchBox from 'components/common/SearchBox';
|
||||
import LeadsFilterModal from 'components/modals/LeadsFilterModal';
|
||||
import LeadsTable, { leadsTableColumns } from 'components/tables/LeadsTable';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { leadsTableData } from 'data/crm/leadsTableData';
|
||||
import useAdvanceTable from 'hooks/useAdvanceTable';
|
||||
import AdvanceTableProvider from 'providers/AdvanceTableProvider';
|
||||
import { useState, ChangeEvent } from 'react';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
|
||||
const Leads = () => {
|
||||
const table = useAdvanceTable({
|
||||
data: leadsTableData,
|
||||
columns: leadsTableColumns,
|
||||
pageSize: 10,
|
||||
pagination: true,
|
||||
sortable: true,
|
||||
selection: true,
|
||||
initialState: {
|
||||
columnVisibility: {
|
||||
status: false,
|
||||
designation: false
|
||||
}
|
||||
}
|
||||
});
|
||||
const [openFilterModal, setOpenFilterModal] = useState(false);
|
||||
const handleSearchInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
table.setGlobalFilter(e.target.value || undefined);
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-6">
|
||||
<AdvanceTableProvider {...table}>
|
||||
<h2 className="mb-4">{leadsTableData.length} Leads</h2>
|
||||
<Row className="g-3 justify-content-between mb-4">
|
||||
<Col xs="auto">
|
||||
<Button
|
||||
variant="primary"
|
||||
className="me-4"
|
||||
startIcon={<FontAwesomeIcon icon={faPlus} className="me-2" />}
|
||||
>
|
||||
Create Lead
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
className="text-body px-0"
|
||||
startIcon={
|
||||
<FontAwesomeIcon icon={faFileExport} className="fs-9 me-2" />
|
||||
}
|
||||
>
|
||||
Export
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs="auto">
|
||||
<div className="d-flex">
|
||||
<SearchBox
|
||||
placeholder="Search by name"
|
||||
className="me-2"
|
||||
onChange={handleSearchInputChange}
|
||||
/>
|
||||
<DatePicker defaultValue="Mar 1, 2022" />
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
className="px-3 ms-2"
|
||||
onClick={() => setOpenFilterModal(true)}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faFilter}
|
||||
transform="down-3"
|
||||
className="text-primary"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
<LeadsFilterModal
|
||||
show={openFilterModal}
|
||||
handleClose={() => setOpenFilterModal(false)}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<LeadsTable />
|
||||
</AdvanceTableProvider>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Leads;
|
||||
54
src/pages/apps/crm/ReportDetails.tsx
Normal file
54
src/pages/apps/crm/ReportDetails.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import ReportDetailsChart from 'components/charts/e-charts/ReportDetailsChart';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import ReportDetailsHeader from 'components/modules/crm/report-details/ReportDetailsHeader';
|
||||
import DealsReportTable, {
|
||||
dealsReportColumns
|
||||
} from 'components/tables/DealsReportTable';
|
||||
import ReportDetailsTable from 'components/tables/ReportDetailsTable';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { dealsReportData } from 'data/crm/reportsData';
|
||||
import useAdvanceTable from 'hooks/useAdvanceTable';
|
||||
import AdvanceTableProvider from 'providers/AdvanceTableProvider';
|
||||
import { Card, Col, Row } from 'react-bootstrap';
|
||||
|
||||
const ReportDetails = () => {
|
||||
const table = useAdvanceTable({
|
||||
data: dealsReportData,
|
||||
columns: dealsReportColumns,
|
||||
pageSize: 10,
|
||||
selection: true,
|
||||
pagination: true,
|
||||
sortable: true
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<AdvanceTableProvider {...table}>
|
||||
<div className="pb-9">
|
||||
<h2 className="mb-4">Purchasers and sellers</h2>
|
||||
<ReportDetailsHeader />
|
||||
<Row className="gy-5">
|
||||
<Col xl={5} xxl={4}>
|
||||
<Card>
|
||||
<Card.Body>
|
||||
<div className="mb-5">
|
||||
<ReportDetailsChart
|
||||
style={{ height: '358px', width: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
<ReportDetailsTable />
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xl={7} xxl={8}>
|
||||
<DealsReportTable />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</AdvanceTableProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReportDetails;
|
||||
61
src/pages/apps/crm/Reports.tsx
Normal file
61
src/pages/apps/crm/Reports.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { ColumnDef } from '@tanstack/react-table';
|
||||
import ReportCard from 'components/cards/ReportCard';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Report, reports } from 'data/crm/reportsData';
|
||||
import useAdvanceTable from 'hooks/useAdvanceTable';
|
||||
import AdvanceTableProvider from 'providers/AdvanceTableProvider';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import ReportTopSection from 'components/modules/crm/ReportTopSection';
|
||||
import AdvanceTableFooter from 'components/base/AdvanceTableFooter';
|
||||
|
||||
export const columns: ColumnDef<Report>[] = [
|
||||
{
|
||||
// For filtering and searching projects by priority
|
||||
id: 'priority',
|
||||
accessorFn: ({ priority }) => priority.label
|
||||
},
|
||||
{
|
||||
// For filtering and searching projects by category
|
||||
id: 'category',
|
||||
accessorFn: ({ category }) => category
|
||||
},
|
||||
{
|
||||
// For searching projects by name
|
||||
accessorKey: 'title'
|
||||
}
|
||||
];
|
||||
|
||||
const Reports = () => {
|
||||
const table = useAdvanceTable<Report>({
|
||||
data: reports,
|
||||
columns,
|
||||
pageSize: 10,
|
||||
pagination: true,
|
||||
sortable: true
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<AdvanceTableProvider {...table}>
|
||||
<div className="mb-9">
|
||||
<h2 className="mb-4">Reports</h2>
|
||||
<ReportTopSection />
|
||||
<Row className="g-3">
|
||||
{table
|
||||
.getRowModel()
|
||||
.rows.map(row => row.original)
|
||||
.map(report => (
|
||||
<Col xl={6} key={report.id}>
|
||||
<ReportCard report={report} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
<AdvanceTableFooter pagination className="mt-2 pb-0" />
|
||||
</div>
|
||||
</AdvanceTableProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Reports;
|
||||
78
src/pages/apps/e-commerce/admin/AddProduct.tsx
Normal file
78
src/pages/apps/e-commerce/admin/AddProduct.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import Button from 'components/base/Button';
|
||||
import Dropzone from 'components/base/Dropzone';
|
||||
import TinymceEditor from 'components/base/TinymceEditor';
|
||||
import OrganizeFormCard from 'components/cards/OrganizeFormCard';
|
||||
import VariantFormCard from 'components/cards/VariantFormCard';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import InventoryTab from 'components/tabs/InventoryTab';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Col, Form, Row } from 'react-bootstrap';
|
||||
|
||||
const AddProduct = () => {
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<form className="mb-9">
|
||||
<div className="d-flex flex-wrap gap-3 flex-between-end mb-5">
|
||||
<div>
|
||||
<h2 className="mb-2">Add a product</h2>
|
||||
<h5 className="text-body-tertiary fw-semibold">
|
||||
Orders placed across your store
|
||||
</h5>
|
||||
</div>
|
||||
<div className="d-flex flex-wrap gap-2">
|
||||
<Button variant="phoenix-secondary" type="button">
|
||||
Discard
|
||||
</Button>
|
||||
<Button variant="phoenix-primary" type="button">
|
||||
Save draft
|
||||
</Button>
|
||||
<Button variant="primary" type="submit">
|
||||
Publish product
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Row className="g-5">
|
||||
<Col xs={12} xl={8}>
|
||||
<h4 className="mb-3">Product Title</h4>
|
||||
<Form.Control placeholder="Write title here..." className="mb-5" />
|
||||
<div className="mb-6">
|
||||
<h4 className="mb-3">Product Description</h4>
|
||||
<TinymceEditor
|
||||
options={{
|
||||
height: '15rem',
|
||||
placeholder: 'Write a description here...'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-5">
|
||||
<h4 className="mb-3">Display images</h4>
|
||||
<Dropzone
|
||||
className="mb-3"
|
||||
accept={{
|
||||
'image/*': ['.png', '.gif', '.jpeg', '.jpg']
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="mb-3">Inventory</h4>
|
||||
<InventoryTab />
|
||||
</div>
|
||||
</Col>
|
||||
<Col xs={12} xl={4}>
|
||||
<Row className="g-2">
|
||||
<Col xs={12} xl={12}>
|
||||
<OrganizeFormCard className="mb-3" />
|
||||
</Col>
|
||||
<Col xs={12} xl={12}>
|
||||
<VariantFormCard />
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddProduct;
|
||||
110
src/pages/apps/e-commerce/admin/CustomerDetails.tsx
Normal file
110
src/pages/apps/e-commerce/admin/CustomerDetails.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import { faKey, faPen, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import CustomerNotesCard from 'components/cards/CustomerNotesCard';
|
||||
import CustomerProfileCard from 'components/cards/CustomerProfileCard';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import CustomerOrdersTable from 'components/tables/CustomerOrdersTable';
|
||||
import CustomerRatingsTable from 'components/tables/CustomerRatingsTable';
|
||||
import CustomerWishlistTable from 'components/tables/CustomerWishlistTable';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Card, Col, Row } from 'react-bootstrap';
|
||||
|
||||
const CustomerDetails = () => {
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-9">
|
||||
<Row className="d-flex align-items-center justify-content-between g-3 mb-4">
|
||||
<Col xs="auto">
|
||||
<h2 className="mb-0 flex-1">Customer details</h2>
|
||||
</Col>
|
||||
<Col xs="auto" className="d-flex gap-3 flex-wrap">
|
||||
<Button
|
||||
variant="phoenix-danger"
|
||||
startIcon={<FontAwesomeIcon icon={faTrashAlt} className="me-2" />}
|
||||
>
|
||||
Delete customer
|
||||
</Button>
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
startIcon={<FontAwesomeIcon icon={faKey} className="me-2" />}
|
||||
>
|
||||
Reset password
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="g-5">
|
||||
<Col xs={12} xxl={4}>
|
||||
<Row className="g-3 xxl-0 h-100">
|
||||
<Col xs={12} md={7} xxl={12}>
|
||||
<CustomerProfileCard />
|
||||
</Col>
|
||||
<Col xs={12} md={5} xxl={12}>
|
||||
<Card className="h-100">
|
||||
<Card.Body className="">
|
||||
<div className="d-flex align-items-center mb-3">
|
||||
<h3 className="me-1">Default Address</h3>
|
||||
<Button variant="link" className="p-0">
|
||||
<FontAwesomeIcon
|
||||
icon={faPen}
|
||||
className="fs-8 ms-3 text-body-quaternary"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
<h5 className="text-body-secondary">Address</h5>
|
||||
<p className="text-body-secondary">
|
||||
Shatinon Mekalan
|
||||
<br />
|
||||
Vancouver, British Columbia
|
||||
<br />
|
||||
Canada
|
||||
</p>
|
||||
<div className="mb-3">
|
||||
<h5 className="text-body-secondary">Email</h5>
|
||||
<a href="mailto:shatinon@jeemail.com">
|
||||
shatinon@jeemail.com
|
||||
</a>
|
||||
</div>
|
||||
<h5 className="text-body-secondary">Phone</h5>
|
||||
<a href="tel:+1234567890">+1234567890</a>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xs={12}>
|
||||
<CustomerNotesCard className="h-100" />
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xs={12} xxl={8}>
|
||||
<div className="d-flex flex-column gap-6">
|
||||
<div>
|
||||
<h3 className="mb-4">
|
||||
Orders{' '}
|
||||
<span className="text-body-tertiary fw-normal">(97)</span>
|
||||
</h3>
|
||||
<CustomerOrdersTable />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="mb-4">
|
||||
Wishlist{' '}
|
||||
<span className="text-body-tertiary fw-normal">(43)</span>
|
||||
</h3>
|
||||
<CustomerWishlistTable />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="mb-4">
|
||||
Ratings & reviews{' '}
|
||||
<span className="text-body-tertiary fw-normal">(43)</span>
|
||||
</h3>
|
||||
<CustomerRatingsTable />
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CustomerDetails;
|
||||
136
src/pages/apps/e-commerce/admin/Customers.tsx
Normal file
136
src/pages/apps/e-commerce/admin/Customers.tsx
Normal file
@@ -0,0 +1,136 @@
|
||||
import { faFileExport, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import FilterButtonGroup, {
|
||||
FilterMenu
|
||||
} from 'components/common/FilterButtonGroup';
|
||||
import FilterTab, { FilterTabItem } from 'components/common/FilterTab';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import SearchBox from 'components/common/SearchBox';
|
||||
import CustomersTable, {
|
||||
customersTablecolumns
|
||||
} from 'components/tables/CustomersTable';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { customers } from 'data/e-commerce/customers';
|
||||
import useAdvanceTable from 'hooks/useAdvanceTable';
|
||||
import AdvanceTableProvider from 'providers/AdvanceTableProvider';
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
const tabItems: FilterTabItem[] = [
|
||||
{
|
||||
label: 'All',
|
||||
value: 'all',
|
||||
count: 68817
|
||||
},
|
||||
{
|
||||
label: 'New',
|
||||
value: 'new',
|
||||
count: 6
|
||||
},
|
||||
{
|
||||
label: 'Abandoned checkouts',
|
||||
value: 'abandoned_checkouts',
|
||||
count: 17
|
||||
},
|
||||
{
|
||||
label: 'Locals',
|
||||
value: 'locals',
|
||||
count: 6810
|
||||
},
|
||||
{
|
||||
label: 'Email subscribers',
|
||||
value: 'email_subscribers',
|
||||
count: 8
|
||||
},
|
||||
{
|
||||
label: 'Top reviews',
|
||||
value: 'top_reviews',
|
||||
count: 2
|
||||
}
|
||||
];
|
||||
|
||||
const filterMenus: FilterMenu[] = [
|
||||
{
|
||||
label: 'Country',
|
||||
items: [
|
||||
{
|
||||
label: 'USA'
|
||||
},
|
||||
{
|
||||
label: 'UK'
|
||||
},
|
||||
{
|
||||
label: 'Australia'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'VIP',
|
||||
items: [
|
||||
{
|
||||
label: 'VIP 1'
|
||||
},
|
||||
{
|
||||
label: 'VIP 2'
|
||||
},
|
||||
{
|
||||
label: 'VIP 3'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const Customers = () => {
|
||||
const table = useAdvanceTable({
|
||||
data: customers,
|
||||
columns: customersTablecolumns,
|
||||
pageSize: 10,
|
||||
pagination: true,
|
||||
sortable: true,
|
||||
selection: true
|
||||
});
|
||||
|
||||
const handleSearchInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
table.setGlobalFilter(e.target.value || undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-9">
|
||||
<h2 className="mb-4">Customers</h2>
|
||||
<FilterTab tabItems={tabItems} className="mb-2" />
|
||||
|
||||
<AdvanceTableProvider {...table}>
|
||||
<div className="mb-4">
|
||||
<div className="d-flex flex-wrap gap-3">
|
||||
<SearchBox
|
||||
placeholder="Search customers"
|
||||
onChange={handleSearchInputChange}
|
||||
/>
|
||||
<div className="scrollbar overflow-hidden-y">
|
||||
<FilterButtonGroup menus={filterMenus} />
|
||||
</div>
|
||||
<div className="ms-xxl-auto">
|
||||
<Button variant="link" className="text-body me-4 px-0">
|
||||
<FontAwesomeIcon icon={faFileExport} className="fs-9 me-2" />
|
||||
Export
|
||||
</Button>
|
||||
<Button variant="primary">
|
||||
<FontAwesomeIcon icon={faPlus} className="me-2" />
|
||||
Add customer
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis border-top border-bottom border-translucent position-relative top-1">
|
||||
<CustomersTable />
|
||||
</div>
|
||||
</AdvanceTableProvider>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Customers;
|
||||
114
src/pages/apps/e-commerce/admin/OrderDetails.tsx
Normal file
114
src/pages/apps/e-commerce/admin/OrderDetails.tsx
Normal file
@@ -0,0 +1,114 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import OrderDetailsTable from 'components/tables/OrderDetailsTable';
|
||||
import { Card, Col, Dropdown, Form, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import OrderDetailsSummaryCard from 'components/cards/OrderDetailsSummaryCard';
|
||||
import {
|
||||
BillingDetails,
|
||||
OtherDetails,
|
||||
ShippingDetails
|
||||
} from 'components/modules/e-commerce/OrderDeliveryDetails';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import {
|
||||
faChevronDown,
|
||||
faPrint,
|
||||
faUndo
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
const OrderDetails = () => {
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-9">
|
||||
<h2 className="mb-1">
|
||||
Order <span>#349</span>
|
||||
</h2>
|
||||
<div className="d-flex flex-wrap flex-between-center mb-3 gap-2">
|
||||
<p className="text-body-secondary lh-sm mb-0">
|
||||
Customer ID :{' '}
|
||||
<Link className="fw-bold" to="#!">
|
||||
{' '}
|
||||
2364847
|
||||
</Link>
|
||||
</p>
|
||||
<div className="d-flex">
|
||||
<Button
|
||||
variant="link"
|
||||
className="ps-0 pe-3 text-body text-decoration-none"
|
||||
startIcon={<FontAwesomeIcon icon={faPrint} className="me-2" />}
|
||||
>
|
||||
Print
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
className="px-3 text-body text-decoration-none"
|
||||
startIcon={<FontAwesomeIcon icon={faUndo} className="me-2" />}
|
||||
>
|
||||
Refund
|
||||
</Button>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
variant=""
|
||||
className="ps-3 pe-0 dropdown-caret-none text-decoration-none"
|
||||
>
|
||||
More action
|
||||
<FontAwesomeIcon icon={faChevronDown} className="ms-2" />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu align="end">
|
||||
<Dropdown.Item href="#/action-1">Action</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-2">Another action</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<Row className="g-5 gy-7">
|
||||
<Col xs={12} xl={8} xxl={9}>
|
||||
<div className="mb-6">
|
||||
<OrderDetailsTable />
|
||||
</div>
|
||||
<Row className="gx-4 gy-6 g-xl-7 justify-content-sm-center justify-content-xl-start">
|
||||
<Col xs={12} sm="auto">
|
||||
<BillingDetails />
|
||||
</Col>
|
||||
|
||||
<Col xs={12} sm="auto">
|
||||
<ShippingDetails />
|
||||
</Col>
|
||||
|
||||
<Col xs={12} sm="auto">
|
||||
<OtherDetails />
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xs={12} xl={4} xxl={3}>
|
||||
<OrderDetailsSummaryCard className="mb-4" />
|
||||
<Card>
|
||||
<Card.Body>
|
||||
<Card.Title as="h3" className="mb-4">
|
||||
Order Status
|
||||
</Card.Title>
|
||||
<h6 className="mb-2">Payment status</h6>
|
||||
<Form.Select className="mb-4">
|
||||
<option value="processing">Processing</option>
|
||||
<option value="canceled">Canceled</option>
|
||||
<option value="completed">Completed</option>
|
||||
</Form.Select>
|
||||
<h6 className="mb-2">Fulfillment status</h6>
|
||||
<Form.Select>
|
||||
<option value="unfulfilled">Unfulfilled</option>
|
||||
<option value="fulfilled">Fulfilled</option>
|
||||
<option value="Pending">Pending</option>
|
||||
</Form.Select>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OrderDetails;
|
||||
134
src/pages/apps/e-commerce/admin/Orders.tsx
Normal file
134
src/pages/apps/e-commerce/admin/Orders.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import { faFileExport, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import FilterButtonGroup, {
|
||||
FilterMenu
|
||||
} from 'components/common/FilterButtonGroup';
|
||||
import FilterTab, { FilterTabItem } from 'components/common/FilterTab';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import SearchBox from 'components/common/SearchBox';
|
||||
import OrdersTable, { ordersTableColumns } from 'components/tables/OrdersTable';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { ordersTableData } from 'data/e-commerce/orders';
|
||||
import useAdvanceTable from 'hooks/useAdvanceTable';
|
||||
import AdvanceTableProvider from 'providers/AdvanceTableProvider';
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
const tabItems: FilterTabItem[] = [
|
||||
{
|
||||
label: 'All',
|
||||
value: 'all',
|
||||
count: 68817
|
||||
},
|
||||
{
|
||||
label: 'Pending payment',
|
||||
value: 'pending_payment',
|
||||
count: 6
|
||||
},
|
||||
{
|
||||
label: 'Unfulfilled',
|
||||
value: 'unfulfilled',
|
||||
count: 17
|
||||
},
|
||||
{
|
||||
label: 'Completed',
|
||||
value: 'completed',
|
||||
count: 6810
|
||||
},
|
||||
{
|
||||
label: 'Refunded',
|
||||
value: 'refunded',
|
||||
count: 8
|
||||
},
|
||||
{
|
||||
label: 'Failed',
|
||||
value: 'failed',
|
||||
count: 2
|
||||
}
|
||||
];
|
||||
|
||||
const filterMenus: FilterMenu[] = [
|
||||
{
|
||||
label: 'Payment status',
|
||||
items: [
|
||||
{
|
||||
label: 'Action'
|
||||
},
|
||||
{
|
||||
label: 'Another Action'
|
||||
},
|
||||
{
|
||||
label: 'Something else here'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Fulfilment status',
|
||||
items: [
|
||||
{
|
||||
label: 'Action'
|
||||
},
|
||||
{
|
||||
label: 'Another Action'
|
||||
},
|
||||
{
|
||||
label: 'Something else here'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const Orders = () => {
|
||||
const table = useAdvanceTable({
|
||||
data: ordersTableData,
|
||||
columns: ordersTableColumns,
|
||||
pageSize: 10,
|
||||
pagination: true,
|
||||
sortable: true,
|
||||
selection: true
|
||||
});
|
||||
|
||||
const handleSearchInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
table.setGlobalFilter(e.target.value || undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-9">
|
||||
<h2 className="mb-4">Orders</h2>
|
||||
<FilterTab tabItems={tabItems} className="mb-2" />
|
||||
|
||||
<AdvanceTableProvider {...table}>
|
||||
<div className="mb-4">
|
||||
<div className="d-flex flex-wrap gap-3">
|
||||
<SearchBox
|
||||
placeholder="Search orders"
|
||||
onChange={handleSearchInputChange}
|
||||
/>
|
||||
<div className="scrollbar overflow-hidden-y">
|
||||
<FilterButtonGroup menus={filterMenus} />
|
||||
</div>
|
||||
<div className="ms-xxl-auto">
|
||||
<Button variant="link" className="text-body me-4 px-0">
|
||||
<FontAwesomeIcon icon={faFileExport} className="fs-9 me-2" />
|
||||
Export
|
||||
</Button>
|
||||
<Button variant="primary">
|
||||
<FontAwesomeIcon icon={faPlus} className="me-2" />
|
||||
Add order
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis border-top border-bottom border-translucent position-relative top-1">
|
||||
<OrdersTable />
|
||||
</div>
|
||||
</AdvanceTableProvider>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Orders;
|
||||
125
src/pages/apps/e-commerce/admin/Products.tsx
Normal file
125
src/pages/apps/e-commerce/admin/Products.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
import { faFileExport, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import FilterButtonGroup, {
|
||||
FilterMenu
|
||||
} from 'components/common/FilterButtonGroup';
|
||||
import FilterTab, { FilterTabItem } from 'components/common/FilterTab';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import SearchBox from 'components/common/SearchBox';
|
||||
import ProductsTable, {
|
||||
productsTablecolumns
|
||||
} from 'components/tables/ProductsTable';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { productsTableData } from 'data/e-commerce/products';
|
||||
import useAdvanceTable from 'hooks/useAdvanceTable';
|
||||
import AdvanceTableProvider from 'providers/AdvanceTableProvider';
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
const tabItems: FilterTabItem[] = [
|
||||
{
|
||||
label: 'All',
|
||||
value: 'all',
|
||||
count: 68817
|
||||
},
|
||||
{
|
||||
label: 'Published',
|
||||
value: 'published',
|
||||
count: 70348
|
||||
},
|
||||
{
|
||||
label: 'Drafts',
|
||||
value: 'drafts',
|
||||
count: 17
|
||||
},
|
||||
{
|
||||
label: 'On discount',
|
||||
value: 'on_discount',
|
||||
count: 810
|
||||
}
|
||||
];
|
||||
|
||||
const filterMenus: FilterMenu[] = [
|
||||
{
|
||||
label: 'Category',
|
||||
items: [
|
||||
{
|
||||
label: 'Plants'
|
||||
},
|
||||
{
|
||||
label: 'Furniture'
|
||||
},
|
||||
{
|
||||
label: 'Fashion'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Vendor',
|
||||
items: [
|
||||
{
|
||||
label: 'Blue Olive Plant sellers. Inc'
|
||||
},
|
||||
{
|
||||
label: 'Beatrice Furnitures'
|
||||
},
|
||||
{
|
||||
label: 'Kizzstore'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const Products = () => {
|
||||
const table = useAdvanceTable({
|
||||
data: productsTableData,
|
||||
columns: productsTablecolumns,
|
||||
pageSize: 10,
|
||||
pagination: true,
|
||||
sortable: true,
|
||||
selection: true
|
||||
});
|
||||
|
||||
const handleSearchInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
table.setGlobalFilter(e.target.value || undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-9">
|
||||
<h2 className="mb-4">Products</h2>
|
||||
<FilterTab tabItems={tabItems} className="mb-2" />
|
||||
<AdvanceTableProvider {...table}>
|
||||
<div className="mb-4">
|
||||
<div className="d-flex flex-wrap gap-3">
|
||||
<SearchBox
|
||||
placeholder="Search products"
|
||||
onChange={handleSearchInputChange}
|
||||
/>
|
||||
<div className="scrollbar overflow-hidden-y">
|
||||
<FilterButtonGroup menus={filterMenus} />
|
||||
</div>
|
||||
<div className="ms-xxl-auto">
|
||||
<Button variant="link" className="text-body me-4 px-0">
|
||||
<FontAwesomeIcon icon={faFileExport} className="fs-9 me-2" />
|
||||
Export
|
||||
</Button>
|
||||
<Button variant="primary">
|
||||
<FontAwesomeIcon icon={faPlus} className="me-2" />
|
||||
Add product
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis border-top border-bottom border-translucent position-relative top-1">
|
||||
<ProductsTable />
|
||||
</div>
|
||||
</AdvanceTableProvider>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Products;
|
||||
77
src/pages/apps/e-commerce/admin/Refund.tsx
Normal file
77
src/pages/apps/e-commerce/admin/Refund.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import OrderDetailsTable from 'components/tables/OrderDetailsTable';
|
||||
import { Card, Col, Dropdown, Form, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import OrderDetailsSummaryCard from 'components/cards/OrderDetailsSummaryCard';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
const Refund = () => {
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-9">
|
||||
<h2 className="mb-3">Refund</h2>
|
||||
<div className="d-flex flex-wrap align-items-center mb-4 gap-3">
|
||||
<p className="text-body-secondary lh-sm mb-0">
|
||||
Order :{' '}
|
||||
<Link className="fw-bold" to="#!">
|
||||
{' '}
|
||||
#349
|
||||
</Link>
|
||||
</p>
|
||||
<div className="flex-1 d-flex flex-between-center gap-3">
|
||||
<p className="text-body-secondary lh-sm mb-0 flex-1 white-space-nowrap">
|
||||
Customer Id :{' '}
|
||||
<Link className="fw-bold" to="#!">
|
||||
{' '}
|
||||
2364847
|
||||
</Link>
|
||||
</p>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
variant=""
|
||||
className="p-0 dropdown-caret-none text-decoration-none"
|
||||
>
|
||||
More action
|
||||
<FontAwesomeIcon icon={faChevronDown} className="ms-2" />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu align="end">
|
||||
<Dropdown.Item href="#/action-1">Action</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-2">Another action</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<Row className="g-5 gy-7">
|
||||
<Col xs={12} xl={8} xxl={9}>
|
||||
<OrderDetailsTable />
|
||||
</Col>
|
||||
<Col xs={12} xl={4} xxl={3}>
|
||||
<OrderDetailsSummaryCard className="mb-4" />
|
||||
<Card>
|
||||
<Card.Body>
|
||||
<Card.Title as="h4" className="mb-4">
|
||||
Refund Amount
|
||||
</Card.Title>
|
||||
<Form.Control
|
||||
type="number"
|
||||
placeholder="Amount"
|
||||
className="mb-4 input-spin-none"
|
||||
/>
|
||||
<Button variant="primary" className="w-100">
|
||||
Refund $500
|
||||
</Button>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Refund;
|
||||
28
src/pages/apps/e-commerce/customer/Cart.tsx
Normal file
28
src/pages/apps/e-commerce/customer/Cart.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import Section from 'components/base/Section';
|
||||
import EcomCartSummaryCard from 'components/cards/EcomCartSummaryCard';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import EcomCartTable from 'components/tables/EcomCartTable';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { cartItems } from 'data/e-commerce/products';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
|
||||
const Cart = () => {
|
||||
return (
|
||||
<div className="pt-5 mb-9">
|
||||
<Section small className="py-0">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<h2 className="mb-6">Cart</h2>
|
||||
<Row className="g-5">
|
||||
<Col xs={12} lg={8}>
|
||||
<EcomCartTable products={cartItems} />
|
||||
</Col>
|
||||
<Col xs={12} lg={4}>
|
||||
<EcomCartSummaryCard />
|
||||
</Col>
|
||||
</Row>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Cart;
|
||||
32
src/pages/apps/e-commerce/customer/FavoriteStores.tsx
Normal file
32
src/pages/apps/e-commerce/customer/FavoriteStores.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import Section from 'components/base/Section';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import StoreItem from 'components/common/StoreItem';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { stores } from 'data/e-commerce/stores';
|
||||
import React from 'react';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
|
||||
const FavoriteStores = () => {
|
||||
return (
|
||||
<div className="pt-5 mb-9">
|
||||
<Section small className="py-0">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="mb-5">
|
||||
<h2>My Favorite Stores</h2>
|
||||
<p className="mb-0 text-body-tertiary fw-semibold">
|
||||
Essential for a better life
|
||||
</p>
|
||||
</div>
|
||||
<Row className="gx-3 gy-5">
|
||||
{stores.map(store => (
|
||||
<Col key={store.name} xs={6} sm={4} md={3} lg={2}>
|
||||
<StoreItem store={store} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FavoriteStores;
|
||||
68
src/pages/apps/e-commerce/customer/Homepage.tsx
Normal file
68
src/pages/apps/e-commerce/customer/Homepage.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import EcomCategoryNavs from 'components/navs/EcomCategoryNavs';
|
||||
import { Col, Container, Row } from 'react-bootstrap';
|
||||
import EcomWhopingBanner from 'components/banners/EcomWhopingBanner';
|
||||
import EcomGiftItemsBanner from 'components/banners/EcomGiftItemsBanner';
|
||||
import EcomBestInMarketBanner from 'components/banners/EcomBestInMarketBanner';
|
||||
import {
|
||||
bestOfferProducts,
|
||||
topDealsProducts,
|
||||
topElectronicProducts
|
||||
} from 'data/e-commerce/products';
|
||||
import ecom4 from 'assets/img/e-commerce/4.png';
|
||||
import EcomTopDeals from 'components/sliders/EcomTopDeals';
|
||||
import EcomTopElectronics from 'components/sliders/EcomTopElectronics';
|
||||
import EcomBestOffers from 'components/sliders/EcomBestOffers';
|
||||
import EcomBecomeMember from 'components/cta/EcomBecomeMember';
|
||||
|
||||
const Homepage = () => {
|
||||
return (
|
||||
<div className="ecommerce-homepage pt-5 mb-9">
|
||||
<section className="py-0">
|
||||
<div className="container-small">
|
||||
<div className="scrollbar">
|
||||
<EcomCategoryNavs />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="py-0 px-xl-3">
|
||||
<Container className="px-xl-0 px-xxl-3">
|
||||
<Row className="g-3 mb-9">
|
||||
<Col xs={12}>
|
||||
<EcomWhopingBanner />
|
||||
</Col>
|
||||
<Col xs={12} xl={6}>
|
||||
<EcomGiftItemsBanner />
|
||||
</Col>
|
||||
<Col xs={12} xl={6}>
|
||||
<EcomBestInMarketBanner />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="g-4 mb-6">
|
||||
<Col xs={12} lg={9} xxl={10}>
|
||||
<EcomTopDeals products={topDealsProducts} />
|
||||
</Col>
|
||||
<Col lg={3} xxl={2} className="d-none d-lg-block">
|
||||
<div className="h-100 position-relative rounded-3 overflow-hidden">
|
||||
<div
|
||||
className="bg-holder product-bg"
|
||||
style={{
|
||||
backgroundImage: `url(${ecom4})`
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="mb-6">
|
||||
<EcomTopElectronics products={topElectronicProducts} />
|
||||
</div>
|
||||
<div className="mb-6">
|
||||
<EcomBestOffers products={bestOfferProducts} />
|
||||
</div>
|
||||
<EcomBecomeMember />
|
||||
</Container>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Homepage;
|
||||
166
src/pages/apps/e-commerce/customer/Invoice.tsx
Normal file
166
src/pages/apps/e-commerce/customer/Invoice.tsx
Normal file
@@ -0,0 +1,166 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import Section from 'components/base/Section';
|
||||
import EcomInvoiceTable from 'components/tables/EcomInvoiceTable';
|
||||
import React from 'react';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import phoenixMart from 'assets/img/logos/phoenix-mart.png';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import {
|
||||
faBagShopping,
|
||||
faDownload,
|
||||
faPrint
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
const Invoice = () => {
|
||||
return (
|
||||
<div className="pt-5 pb-9 bg-body-emphasis dark__bg-gray-1200 border-top">
|
||||
<Section small className="py-0">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="d-flex gap-2 justify-content-between align-items-end mb-4">
|
||||
<h2 className="mb-0 flex-1">Invoice</h2>
|
||||
<Button variant="phoenix-secondary">
|
||||
<FontAwesomeIcon icon={faDownload} className="me-sm-2" />
|
||||
<span className="d-none d-sm-inline-block">Download Invoice</span>
|
||||
</Button>
|
||||
<Button variant="phoenix-secondary">
|
||||
<FontAwesomeIcon icon={faPrint} className="me-sm-2" />
|
||||
<span className="d-none d-sm-inline-block">Print</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="bg-body dark__bg-gray-1100 p-4 mb-4 rounded-2">
|
||||
<Row className="g-4">
|
||||
<Col xs={12} lg={3}>
|
||||
<Row className="g-4 g-lg-2">
|
||||
<Col xs={12} sm={6} lg={12}>
|
||||
<Row className=" align-items-center g-0">
|
||||
<Col xs="auto" lg={6} xl={5}>
|
||||
<h6 className="mb-0 me-3">Invoice No :</h6>
|
||||
</Col>
|
||||
<Col xs="auto" lg={6} xl={7}>
|
||||
<p className="fs-9 text-body-secondary fw-semibold mb-0">
|
||||
#FLR978282
|
||||
</p>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xs={12} sm={6} lg={12}>
|
||||
<Row className=" align-items-center g-0">
|
||||
<Col xs="auto" lg={6} xl={5}>
|
||||
<h6 className="me-3">Invoice Date :</h6>
|
||||
</Col>
|
||||
<Col xs="auto" lg={6} xl={7}>
|
||||
<p className="fs-9 text-body-secondary fw-semibold mb-0">
|
||||
19.06.2019
|
||||
</p>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xs={12} sm={6} lg={5}>
|
||||
<Row className="g-4 gy-lg-5">
|
||||
<Col xs={12} lg={8}>
|
||||
<h6 className="mb-2 me-3">Sold by :</h6>
|
||||
<p className="fs-9 text-body-secondary fw-semibold mb-0">
|
||||
PhoenixMart
|
||||
<br />
|
||||
36 greendowm road, California, Usa
|
||||
</p>
|
||||
</Col>
|
||||
<Col xs={12} lg={4}>
|
||||
<h6 className="mb-2"> PAN No :</h6>
|
||||
<p className="fs-9 text-body-secondary fw-semibold mb-0">
|
||||
XVCJ963782008
|
||||
</p>
|
||||
</Col>
|
||||
<Col xs={12} lg={4}>
|
||||
<h6 className="mb-2"> GST Reg No :</h6>
|
||||
<p className="fs-9 text-body-secondary fw-semibold mb-0">
|
||||
IX9878123TC
|
||||
</p>
|
||||
</Col>
|
||||
<Col xs={12} lg={4}>
|
||||
<h6 className="mb-2"> Order No :</h6>
|
||||
<p className="fs-9 text-body-secondary fw-semibold mb-0">
|
||||
A-8934792734
|
||||
</p>
|
||||
</Col>
|
||||
<Col xs={12} lg={4}>
|
||||
<h6 className="mb-2"> Order Date :</h6>
|
||||
<p className="fs-9 text-body-secondary fw-semibold mb-0">
|
||||
19.06.2019
|
||||
</p>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xs={12} sm={6} lg={4}>
|
||||
<Row className="g-4">
|
||||
<Col xs={12} lg={6}>
|
||||
<h6 className="mb-2"> Billing Address :</h6>
|
||||
<div className="fs-9 text-body-secondary fw-semibold mb-0">
|
||||
<p className="mb-2">John Doe,</p>
|
||||
<p className="mb-2">
|
||||
36, Gree Donwtonwn,
|
||||
<br />
|
||||
Golden road, FL,
|
||||
</p>
|
||||
<p className="mb-2">johndoe@jeemail.com</p>
|
||||
<p className="mb-0">+334933029030</p>
|
||||
</div>
|
||||
</Col>
|
||||
<Col xs={12} lg={6}>
|
||||
<h6 className="mb-2"> Shipping Address :</h6>
|
||||
<div className="fs-9 text-body-secondary fw-semibold mb-0">
|
||||
<p className="mb-2">John Doe,</p>
|
||||
<p className="mb-2">
|
||||
36, Gree Donwtonwn,
|
||||
<br />
|
||||
Golden road, FL,
|
||||
</p>
|
||||
<p className="mb-2">johndoe@jeemail.com</p>
|
||||
<p className="mb-0">+334933029030</p>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<EcomInvoiceTable />
|
||||
|
||||
<div className="text-end py-9 border-bottom">
|
||||
<img className="mb-3" src={phoenixMart} alt="phoenix-mart" />
|
||||
<h4>Authorized Signatory</h4>
|
||||
</div>
|
||||
|
||||
<div className="text-center py-4 mb-9">
|
||||
<p className="mb-0">
|
||||
Thank you for buying with Phoenix | 2022 ©{' '}
|
||||
<a href="https://themewagon.com/">Themewagon</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="d-flex justify-content-between">
|
||||
<button className="btn btn-primary">
|
||||
<FontAwesomeIcon icon={faBagShopping} className="me-2" />
|
||||
Browse more items
|
||||
</button>
|
||||
<div>
|
||||
<button className="btn btn-phoenix-secondary me-2">
|
||||
<FontAwesomeIcon icon={faDownload} className="me-sm-2" />
|
||||
<span className="d-none d-sm-inline-block">Download Invoice</span>
|
||||
</button>
|
||||
<button className="btn btn-phoenix-secondary">
|
||||
<FontAwesomeIcon icon={faPrint} className="me-sm-2" />
|
||||
<span className="d-none d-sm-inline-block">Print</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Invoice;
|
||||
54
src/pages/apps/e-commerce/customer/OrderTracking.tsx
Normal file
54
src/pages/apps/e-commerce/customer/OrderTracking.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { faPhone } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import Mapbox from 'components/base/MapBox';
|
||||
import Section from 'components/base/Section';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import OrderTrackingTimeline from 'components/timelines/OrderTrackingTimeline';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { orderTrackingTimelineData } from 'data/timelineData';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
|
||||
const OrderTracking = () => {
|
||||
return (
|
||||
<div className="pt-5 mb-9">
|
||||
<Section small className="py-0">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<div className="d-flex gap-3 flex-wrap justify-content-between align-items-end mb-5">
|
||||
<div>
|
||||
<h2>Order #234 Status</h2>
|
||||
<p className="text-body-secondary mb-0">
|
||||
Payment Via{' '}
|
||||
<a className="fw-bold" href="#!">
|
||||
Cash on delivery
|
||||
</a>
|
||||
,<br className="d-sm-none" />
|
||||
<span className="ms-sm-1">Nov 12, 2021, 8:54AM.</span>
|
||||
</p>
|
||||
</div>
|
||||
<Button variant="outline-primary">
|
||||
<FontAwesomeIcon icon={faPhone} className="me-2" />
|
||||
Call Support
|
||||
</Button>
|
||||
</div>
|
||||
<Row className="gy-9 gx-5">
|
||||
<Col xs={12} lg={6}>
|
||||
<Mapbox
|
||||
className="border rounded-3 min-vh-50"
|
||||
options={{
|
||||
center: [-74.0020158, 40.7228022],
|
||||
zoom: 15,
|
||||
scrollZoom: false
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} lg={6}>
|
||||
<OrderTrackingTimeline data={orderTrackingTimelineData} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OrderTracking;
|
||||
30
src/pages/apps/e-commerce/customer/ProductDetails.tsx
Normal file
30
src/pages/apps/e-commerce/customer/ProductDetails.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import ProductDescription from 'components/modules/e-commerce/ProductDescription';
|
||||
import ProductDetailsTab from 'components/modules/e-commerce/ProductDetailsTab';
|
||||
import { topElectronicProducts } from 'data/e-commerce/products';
|
||||
import SimilarProducts from 'components/sliders/SimilarProducts';
|
||||
import Section from 'components/base/Section';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { ecomBreadcrumbItems } from 'data/commonData';
|
||||
|
||||
const ProductDetails = () => {
|
||||
return (
|
||||
<div className="pt-5 mb-9">
|
||||
<Section small className="py-0">
|
||||
<PageBreadcrumb items={ecomBreadcrumbItems} className="mb-3" />
|
||||
<ProductDescription />
|
||||
</Section>
|
||||
|
||||
<Section small className="py-0">
|
||||
<div className="mb-9">
|
||||
<ProductDetailsTab />
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section className="py-0">
|
||||
<SimilarProducts products={topElectronicProducts} />
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductDetails;
|
||||
88
src/pages/apps/e-commerce/customer/ProductsFilter.tsx
Normal file
88
src/pages/apps/e-commerce/customer/ProductsFilter.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import PhoenixOffcanvas from 'components/base/PhoenixOffcanvas';
|
||||
import Section from 'components/base/Section';
|
||||
import { useState } from 'react';
|
||||
import { Button, Col, Pagination, Row } from 'react-bootstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Scrollbar from 'components/base/Scrollbar';
|
||||
import ProductFilterItems from 'components/modules/e-commerce/products-filter/ProductFilterItems';
|
||||
import ProductCard from 'components/common/ProductCard';
|
||||
import { allProducts } from 'data/e-commerce/products';
|
||||
import {
|
||||
faChevronLeft,
|
||||
faChevronRight,
|
||||
faFilter
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
const ProductsFilter = () => {
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
const handleClose = () => setShow(false);
|
||||
const handleShow = () => setShow(true);
|
||||
return (
|
||||
<div>
|
||||
<PhoenixOffcanvas
|
||||
open={show}
|
||||
onHide={handleClose}
|
||||
style={{ width: 300, top: 92 }}
|
||||
className="py-5 ps-5"
|
||||
fixed
|
||||
>
|
||||
<Scrollbar className="table-scrollbar">
|
||||
<div className="pe-5">
|
||||
<ProductFilterItems handleClose={handleClose} />
|
||||
</div>
|
||||
</Scrollbar>
|
||||
</PhoenixOffcanvas>
|
||||
<Section className="pt-5 pb-9">
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
size="sm"
|
||||
className="text-body-tertiary mb-5 d-lg-none"
|
||||
onClick={handleShow}
|
||||
>
|
||||
<FontAwesomeIcon icon={faFilter} className="me-2" />
|
||||
Filter
|
||||
</Button>
|
||||
<Row>
|
||||
<Col lg={3} xxl={2} className="d-none d-lg-block ps-xl-0 ps-xxl-3">
|
||||
<div
|
||||
className="position-sticky"
|
||||
style={{ top: '1rem', height: 'calc(100vh - 2rem) ' }}
|
||||
>
|
||||
<Scrollbar className="product-scrollbar">
|
||||
<ProductFilterItems handleClose={handleClose} />
|
||||
</Scrollbar>
|
||||
</div>
|
||||
</Col>
|
||||
<Col lg={9} xxl={10}>
|
||||
<Row className="gx-3 gy-6 mb-8">
|
||||
{allProducts.map(product => (
|
||||
<Col xs={12} sm={6} md={4} xxl={2} key={product.id}>
|
||||
<div className="product-card-container h-100">
|
||||
<ProductCard product={product} />
|
||||
</div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
|
||||
<Pagination className="mb-0 justify-content-end">
|
||||
<Pagination.Prev>
|
||||
<FontAwesomeIcon icon={faChevronLeft} />
|
||||
</Pagination.Prev>
|
||||
<Pagination.Item>1</Pagination.Item>
|
||||
<Pagination.Item>2</Pagination.Item>
|
||||
<Pagination.Item>3</Pagination.Item>
|
||||
<Pagination.Item active>4</Pagination.Item>
|
||||
<Pagination.Item>5</Pagination.Item>
|
||||
<Pagination.Next>
|
||||
<FontAwesomeIcon icon={faChevronRight} />
|
||||
</Pagination.Next>
|
||||
</Pagination>
|
||||
</Col>
|
||||
</Row>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductsFilter;
|
||||
50
src/pages/apps/e-commerce/customer/Profile.tsx
Normal file
50
src/pages/apps/e-commerce/customer/Profile.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import { faKey, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import Section from 'components/base/Section';
|
||||
import EcoimDefaultAddressCard from 'components/cards/EcoimDefaultAddressCard';
|
||||
import EcomProfileCard from 'components/cards/EcomProfileCard';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import ProfileDetailsTab from 'components/modules/e-commerce/profile/ProfileDetailsTab';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
|
||||
const Profile = () => {
|
||||
return (
|
||||
<div className="pt-5 mb-9">
|
||||
<Section small className="py-0">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<Row className="align-items-center justify-content-between g-3 mb-4">
|
||||
<Col xs="auto">
|
||||
<h2 className="mb-0">Profile</h2>
|
||||
</Col>
|
||||
<Col xs="auto" className="d-flex flex-wrap gap-2 gap-sm-3">
|
||||
<Button
|
||||
variant="phoenix-danger"
|
||||
startIcon={<FontAwesomeIcon className="me-2" icon={faTrashAlt} />}
|
||||
>
|
||||
Delete customer
|
||||
</Button>
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
startIcon={<FontAwesomeIcon className="me-2" icon={faKey} />}
|
||||
>
|
||||
Reset password
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="g-3 mb-6">
|
||||
<Col xs={12} lg={8}>
|
||||
<EcomProfileCard />
|
||||
</Col>
|
||||
<Col xs={12} lg={4}>
|
||||
<EcoimDefaultAddressCard />
|
||||
</Col>
|
||||
</Row>
|
||||
<ProfileDetailsTab />
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Profile;
|
||||
21
src/pages/apps/e-commerce/customer/Wishlist.tsx
Normal file
21
src/pages/apps/e-commerce/customer/Wishlist.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import Section from 'components/base/Section';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import EcomWishlistTable from 'components/tables/EcomWishlistTable';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
|
||||
const Wishlist = () => {
|
||||
return (
|
||||
<div className="pt-5 mb-9">
|
||||
<Section small className="py-0">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<h2 className="mb-5">
|
||||
Wishlist
|
||||
<span className="text-body-tertiary fw-normal ms-2">(43)</span>
|
||||
</h2>
|
||||
<EcomWishlistTable />
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Wishlist;
|
||||
67
src/pages/apps/e-commerce/customer/checkout/Checkout.tsx
Normal file
67
src/pages/apps/e-commerce/customer/checkout/Checkout.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import Button from 'components/base/Button';
|
||||
import Section from 'components/base/Section';
|
||||
import { Col, Form, Row } from 'react-bootstrap';
|
||||
import EcomAddressTable from 'components/tables/EcomAddressTable';
|
||||
import { shippingDetailsAddress } from 'data/e-commerce';
|
||||
import DeliveryType from 'components/modules/e-commerce/checkout/DeliveryType';
|
||||
import { PaymentMethod } from 'components/modules/e-commerce/checkout/PaymentMethod';
|
||||
import { currencyFormat } from 'helpers/utils';
|
||||
import CheckoutSummaryCard from 'components/modules/e-commerce/checkout/CheckoutSummaryCard';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
|
||||
const Checkout = () => {
|
||||
return (
|
||||
<div className="pt-5 mb-9">
|
||||
<Section small className="py-0">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<h2 className="mb-5">Check out</h2>
|
||||
<Row className="justify-content-between">
|
||||
<Col lg={7}>
|
||||
<form>
|
||||
<div className="d-flex align-items-end mb-4">
|
||||
<h3 className="mb-0 me-3">Shipping Details</h3>
|
||||
<Button variant="link" className="p-0" type="button">
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
<EcomAddressTable data={shippingDetailsAddress} />
|
||||
<hr className="my-6" />
|
||||
<h3>Billing Details</h3>
|
||||
<Form.Check type="checkbox" id="sameAsShipping" className="mb-4">
|
||||
<Form.Check.Input type="checkbox" />
|
||||
<Form.Check.Label className="fs-8 fw-normal">
|
||||
Same as shipping address
|
||||
</Form.Check.Label>
|
||||
</Form.Check>
|
||||
<EcomAddressTable data={shippingDetailsAddress} />
|
||||
<hr className="my-6" />
|
||||
<DeliveryType />
|
||||
<hr className="my-6" />
|
||||
<PaymentMethod />
|
||||
|
||||
<div className="d-flex flex-column flex-sm-row gap-2 mb-7 mb-lg-0">
|
||||
<Button variant="primary" type="submit" className="w-100">
|
||||
Pay {currencyFormat(695.2)}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
type="submit"
|
||||
className="text-nowrap"
|
||||
>
|
||||
Save Order and Exit
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Col>
|
||||
<Col lg={5} xl={4}>
|
||||
<CheckoutSummaryCard />
|
||||
</Col>
|
||||
</Row>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Checkout;
|
||||
127
src/pages/apps/e-commerce/customer/checkout/ShippingInfo.tsx
Normal file
127
src/pages/apps/e-commerce/customer/checkout/ShippingInfo.tsx
Normal file
@@ -0,0 +1,127 @@
|
||||
import Section from 'components/base/Section';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import CheckoutSummaryCard from 'components/modules/e-commerce/checkout/CheckoutSummaryCard';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Button, Col, Form, Row } from 'react-bootstrap';
|
||||
|
||||
const ShippingInfo = () => {
|
||||
return (
|
||||
<div className="pt-5 mb-9">
|
||||
<Section small className="py-0">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<h2 className="mb-5">Check out</h2>
|
||||
<Row className="justify-content-between gy-6 gx-5">
|
||||
<Col lg={7}>
|
||||
<h3 className="mb-5">Shipping Info</h3>
|
||||
<Row className="g-4">
|
||||
<Col xs={12}>
|
||||
<Form.Group>
|
||||
<label className="form-label text-transform-none ps-0 fs-8 text-body-highlight">
|
||||
Full name
|
||||
</label>
|
||||
<Form.Control type="text" placeholder="Full name" />
|
||||
</Form.Group>
|
||||
</Col>
|
||||
<Col md={6}>
|
||||
<Form.Group>
|
||||
<label className="form-label text-transform-none ps-0 fs-8 text-body-highlight">
|
||||
Email
|
||||
</label>
|
||||
<Form.Control type="email" placeholder="Email" />
|
||||
</Form.Group>
|
||||
</Col>
|
||||
<Col md={6}>
|
||||
<Form.Group>
|
||||
<label className="form-label text-transform-none ps-0 fs-8 text-body-highlight">
|
||||
Phone
|
||||
</label>
|
||||
<Form.Control type="tel" placeholder="+1234567890" />
|
||||
</Form.Group>
|
||||
</Col>
|
||||
<Col md={12}>
|
||||
<Form.Group>
|
||||
<label className="form-label text-transform-none ps-0 fs-8 text-body-highlight">
|
||||
Address line 1
|
||||
</label>
|
||||
<Form.Control type="text" placeholder="Address line 1" />
|
||||
</Form.Group>
|
||||
</Col>
|
||||
<Col md={12}>
|
||||
<Form.Group>
|
||||
<label className="form-label text-transform-none ps-0 fs-8 text-body-highlight">
|
||||
Address line 2
|
||||
</label>
|
||||
<Form.Control type="text" placeholder="Address line 2" />
|
||||
</Form.Group>
|
||||
</Col>
|
||||
<Col md={4}>
|
||||
<Form.Group>
|
||||
<label className="form-label text-transform-none ps-0 fs-8 text-body-highlight">
|
||||
City
|
||||
</label>
|
||||
<Form.Select defaultValue="van-nuys">
|
||||
<option value="van-nuys">Van Nuys</option>
|
||||
<option value="los-angeles">Los Angeles</option>
|
||||
<option value="chicago">Chicago</option>
|
||||
<option value="houston">Houston</option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
</Col>
|
||||
<Col md={4}>
|
||||
<Form.Group>
|
||||
<label className="form-label text-transform-none ps-0 fs-8 text-body-highlight">
|
||||
State
|
||||
</label>
|
||||
<Form.Select defaultValue="california">
|
||||
<option value="california">California</option>
|
||||
<option value="Alaska">Alaska</option>
|
||||
<option value="alabama">Alabama</option>
|
||||
<option value="florida">Florida</option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
</Col>
|
||||
<Col md={4}>
|
||||
<Form.Group>
|
||||
<label className="form-label text-transform-none ps-0 fs-8 text-body-highlight">
|
||||
Zip code
|
||||
</label>
|
||||
<Form.Control type="text" placeholder="Zip code" />
|
||||
</Form.Group>
|
||||
</Col>
|
||||
<Col md={4} className="mb-3">
|
||||
<Form.Group>
|
||||
<label className="form-label text-transform-none ps-0 fs-8 text-body-highlight">
|
||||
Country
|
||||
</label>
|
||||
<Form.Select defaultValue="usa">
|
||||
<option value="usa">USA</option>
|
||||
<option value="uk">UK</option>
|
||||
<option value="aus">AUS</option>
|
||||
<option value="nz">NZ</option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
</Col>
|
||||
<Col xs={12}>
|
||||
<Button className="px-8 px-sm-11 me-2" type="submit">
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
className="text-nowrap"
|
||||
type="button"
|
||||
>
|
||||
Exit Without Saving
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col lg={5} xl={{ span: 4, offset: 1 }}>
|
||||
<CheckoutSummaryCard />
|
||||
</Col>
|
||||
</Row>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShippingInfo;
|
||||
100
src/pages/apps/email/Compose.tsx
Normal file
100
src/pages/apps/email/Compose.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
import {
|
||||
faImage,
|
||||
faPaperPlane,
|
||||
faPaperclip
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import TinymceEditor from 'components/base/TinymceEditor';
|
||||
import EmailLayout from 'layouts/EmailLayout';
|
||||
import { Card, Col, Form, Row } from 'react-bootstrap';
|
||||
|
||||
const Compose = () => {
|
||||
return (
|
||||
<EmailLayout page="compose">
|
||||
<Col>
|
||||
<Card className="email-content">
|
||||
<Card.Body>
|
||||
<form className="d-flex flex-column h-100">
|
||||
<Row className="g-3 mb-2">
|
||||
<Col xs={4}>
|
||||
<Form.Control type="email" placeholder="To" />
|
||||
</Col>
|
||||
<Col xs={4}>
|
||||
<Form.Control type="email" placeholder="CC" />
|
||||
</Col>
|
||||
<Col xs={4}>
|
||||
<Form.Control type="email" placeholder="BCC" />
|
||||
</Col>
|
||||
<Col xs={12}>
|
||||
<Form.Control type="text" placeholder="Subject" />
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="mb-3 flex-1">
|
||||
<TinymceEditor
|
||||
options={{
|
||||
height: '100%'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex justify-content-between align-items-center">
|
||||
<div className="d-flex gap-3">
|
||||
<div>
|
||||
<Button className="p-0">
|
||||
<label
|
||||
className="text-body fs-9 cursor-pointer"
|
||||
htmlFor="attachments"
|
||||
>
|
||||
<FontAwesomeIcon icon={faPaperclip} />
|
||||
</label>
|
||||
</Button>
|
||||
<Form.Control
|
||||
className="d-none"
|
||||
type="file"
|
||||
id="attachments"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Button className="p-0">
|
||||
<label
|
||||
className="text-body fs-9 cursor-pointer"
|
||||
htmlFor="images"
|
||||
>
|
||||
<FontAwesomeIcon icon={faImage} />
|
||||
</label>
|
||||
</Button>
|
||||
<Form.Control
|
||||
className="d-none"
|
||||
type="file"
|
||||
accept="image/*"
|
||||
id="images"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
<Button
|
||||
variant="link"
|
||||
className="text-body fs-10 text-decoration-none"
|
||||
>
|
||||
Discard
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
className="fs-10"
|
||||
type="submit"
|
||||
endIcon={<FontAwesomeIcon icon={faPaperPlane} />}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
</EmailLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default Compose;
|
||||
195
src/pages/apps/email/EmailDetail.tsx
Normal file
195
src/pages/apps/email/EmailDetail.tsx
Normal file
@@ -0,0 +1,195 @@
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Avatar from 'components/base/Avatar';
|
||||
import Button from 'components/base/Button';
|
||||
import EmailLayout from 'layouts/EmailLayout';
|
||||
import { Card, Col, Dropdown, Row } from 'react-bootstrap';
|
||||
import team60 from 'assets/img/team/60.webp';
|
||||
import generic41 from 'assets/img/generic/41.png';
|
||||
import RevealDropdown, {
|
||||
RevealDropdownTrigger
|
||||
} from 'components/base/RevealDropdown';
|
||||
import { Link } from 'react-router-dom';
|
||||
import TooltipIconButton from 'components/common/TooltipIconButton';
|
||||
import AttachmentPreview from 'components/common/AttachmentPreview';
|
||||
import {
|
||||
faAngleLeft,
|
||||
faArchive,
|
||||
faPaperclip,
|
||||
faPrint,
|
||||
faReply,
|
||||
faReplyAll,
|
||||
faShare,
|
||||
faTrashCan
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { faStar } from '@fortawesome/free-regular-svg-icons';
|
||||
import { faStar as farStar } from '@fortawesome/free-regular-svg-icons';
|
||||
|
||||
const EmailDetail = () => {
|
||||
return (
|
||||
<EmailLayout page="detail">
|
||||
<Col>
|
||||
<Card className="email-content">
|
||||
<Card.Header className="border-0">
|
||||
<div className="d-flex flex-between-center pb-3 border-bottom border-translucent">
|
||||
<Button
|
||||
as={Link}
|
||||
to="/apps/email/inbox"
|
||||
variant="link"
|
||||
className="p-0 text-body-secondary me-3"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faAngleLeft}
|
||||
className="fw-bolder fs-8"
|
||||
/>
|
||||
</Button>
|
||||
<h3 className="flex-1 mb-0 lh-sm line-clamp-1">
|
||||
Query about recently purchased soccer socks
|
||||
</h3>
|
||||
|
||||
<RevealDropdownTrigger>
|
||||
<RevealDropdown>
|
||||
<Dropdown.Item>Edit</Dropdown.Item>
|
||||
<Dropdown.Item className="text-danger">Delete</Dropdown.Item>
|
||||
<Dropdown.Item>Download</Dropdown.Item>
|
||||
<Dropdown.Item>Report abuse</Dropdown.Item>
|
||||
</RevealDropdown>
|
||||
</RevealDropdownTrigger>
|
||||
</div>
|
||||
</Card.Header>
|
||||
<Card.Body className="p-0 pb-4 scrollbar">
|
||||
<div className="email-detail-content px-4">
|
||||
<Row className="align-items-center gy-3 gx-2 mb-10">
|
||||
<Col
|
||||
xs={12}
|
||||
sm="auto"
|
||||
lg={12}
|
||||
xl="auto"
|
||||
className="d-flex gap-4 gap-lg-3 gap-xl-4 order-sm-1 order-lg-0 order-xl-1"
|
||||
>
|
||||
<TooltipIconButton title="Reply" icon={faReply} />
|
||||
<TooltipIconButton title="Remove" icon={faTrashCan} />
|
||||
<TooltipIconButton title="Archive" icon={faArchive} />
|
||||
<TooltipIconButton title="Print" icon={faPrint} />
|
||||
<TooltipIconButton title="Star" icon={faStar} />
|
||||
</Col>
|
||||
<Col xs="auto">
|
||||
<Avatar src={team60} size="xl" />
|
||||
</Col>
|
||||
<Col xs="auto" className="flex-1">
|
||||
<div className="d-flex mb-1">
|
||||
<h5 className="mb-0 text-body-highlight me-2">
|
||||
Jessica Ball
|
||||
</h5>
|
||||
<p className="mb-0 lh-sm text-body-tertiary fs-9 d-none d-md-block text-nowrap">
|
||||
< jessica.ball@email.com >
|
||||
</p>
|
||||
</div>
|
||||
<p className="mb-0 fs-9">
|
||||
<span className="text-body-tertiary me-1">to</span>
|
||||
<span className="fw-bold text-body-secondary me-1">Me</span>
|
||||
<span className="text-body-highlight fw-semibold fs-10 me-1">
|
||||
28 Aug, 2021
|
||||
</span>
|
||||
<span className="fw-semibold text-body fs-10 me-1">
|
||||
6:32 PM
|
||||
</span>
|
||||
<FontAwesomeIcon
|
||||
icon={farStar}
|
||||
className="text-body-quaternary"
|
||||
/>
|
||||
</p>
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="text-body-highlight fs-9 w-100 w-md-75 mb-8">
|
||||
<p>Dear Simp sons,</p>
|
||||
<p>
|
||||
Something in a thirty-acre thermal thicket of thorns and
|
||||
thistles thumped and thundered threatening the three-D
|
||||
thoughts of Matthew the thug - although, theatrically, it was
|
||||
only the thirteen-thousand thistles and thorns through the
|
||||
underneath of his thigh that the thirty year old thug thought
|
||||
of that morning.
|
||||
</p>
|
||||
<p>
|
||||
How much caramel can a canny canonball cram in a camel if a
|
||||
canny canonball can cram caramel in a camel? If practice makes
|
||||
perfect and perfect needs practice, I’m perfectly practiced
|
||||
and practically perfect.
|
||||
</p>
|
||||
<p className="mb-0">Best regards,</p>
|
||||
<p>Jess</p>
|
||||
</div>
|
||||
<div className="d-flex align-items-center mb-5">
|
||||
<Button
|
||||
variant="link"
|
||||
className="text-body-highlight fs-8 text-decoration-none p-0"
|
||||
type="button"
|
||||
startIcon={
|
||||
<FontAwesomeIcon icon={faPaperclip} className="me-2" />
|
||||
}
|
||||
>
|
||||
2 Attachments
|
||||
</Button>
|
||||
</div>
|
||||
<Row className="pb-11 border-bottom border-translucent mb-4 gx-0 gy-2">
|
||||
<Col xs="auto" className="me-3">
|
||||
<AttachmentPreview
|
||||
attachment={{
|
||||
name: 'workflow-data.pdf',
|
||||
size: '53.34 KB',
|
||||
format: 'pdf'
|
||||
}}
|
||||
size="xl"
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col xs="auto" className="me-3">
|
||||
<AttachmentPreview
|
||||
attachment={{
|
||||
name: 'forest.jpg',
|
||||
size: '123.34 KB',
|
||||
format: 'jpg',
|
||||
preview: generic41
|
||||
}}
|
||||
size="xl"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="d-flex justify-content-between">
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
className="me-1 text-nowrap px-2 px-sm-4"
|
||||
endIcon={
|
||||
<FontAwesomeIcon icon={faReply} className="ms-2 fs-10" />
|
||||
}
|
||||
>
|
||||
Reply
|
||||
</Button>
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
className="me-1 text-nowrap px-2 px-sm-4"
|
||||
endIcon={
|
||||
<FontAwesomeIcon icon={faReplyAll} className="ms-2 fs-10" />
|
||||
}
|
||||
>
|
||||
Reply All
|
||||
</Button>
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
className="ms-auto text-nowrap px-2 px-sm-4"
|
||||
endIcon={
|
||||
<FontAwesomeIcon icon={faShare} className="ms-2 fs-10" />
|
||||
}
|
||||
>
|
||||
Forward
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
</EmailLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmailDetail;
|
||||
25
src/pages/apps/email/Inbox.tsx
Normal file
25
src/pages/apps/email/Inbox.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import EmailLayout from 'layouts/EmailLayout';
|
||||
import { Col } from 'react-bootstrap';
|
||||
import InboxToolbar from 'components/modules/email/InboxToolbar';
|
||||
import { emails } from 'data/email';
|
||||
import EmailRow from 'components/modules/email/EmailRow';
|
||||
import BulkSelectProvider from 'providers/BulkSelectProvider';
|
||||
|
||||
const Inbox = () => {
|
||||
return (
|
||||
<EmailLayout page="inbox">
|
||||
<Col xs={12} lg>
|
||||
<div className="px-lg-1">
|
||||
<BulkSelectProvider data={emails}>
|
||||
<InboxToolbar className="inbox-toolbar" />
|
||||
{emails.map((email, index) => (
|
||||
<EmailRow index={index} email={email} key={email.id} />
|
||||
))}
|
||||
</BulkSelectProvider>
|
||||
</div>
|
||||
</Col>
|
||||
</EmailLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default Inbox;
|
||||
100
src/pages/apps/events/CreateAnEvent.tsx
Normal file
100
src/pages/apps/events/CreateAnEvent.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
import Button from 'components/base/Button';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import EventCustomFields from 'components/forms/EventCustomFields';
|
||||
import EventDescriptionForm from 'components/forms/EventDescriptionForm';
|
||||
import EventDetailsForm from 'components/forms/EventDetailsForm';
|
||||
import EventTicketPricing from 'components/forms/EventTicketPricing';
|
||||
import EventsSchedule from 'components/forms/EventsSchedule';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Col, Form, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const CreateAnEvent = () => {
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<Form className="mb-9">
|
||||
<Row className="justify-content-between align-items-end g-3 mb-5">
|
||||
<Col xs={12} sm="auto" xl={8}>
|
||||
<h2 className="mb-0">Create an Event</h2>
|
||||
</Col>
|
||||
<Col xs={12} sm="auto" xl={4}>
|
||||
<div className="d-flex">
|
||||
<Button
|
||||
className="px-5 me-2"
|
||||
variant="phoenix-primary"
|
||||
type="button"
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
as={Link}
|
||||
to="/apps/events/event-details"
|
||||
className="px-5 w-100 text-nowrap"
|
||||
>
|
||||
Publish Event
|
||||
</Button>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="g-5">
|
||||
<Col xl={8}>
|
||||
<Row className="gx-3 gy-4">
|
||||
<EventDetailsForm />
|
||||
<EventsSchedule />
|
||||
<EventDescriptionForm />
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xl={4}>
|
||||
<div className="border-bottom border-translucent pb-6 mb-6">
|
||||
<h4 className="mb-4">Privacy</h4>
|
||||
<Form.Check type="radio" id="privacy1" className="mb-2">
|
||||
<Form.Check.Input
|
||||
type="radio"
|
||||
name="vrivacyRadio"
|
||||
value="option1"
|
||||
defaultChecked
|
||||
/>
|
||||
<Form.Check.Label className="fw-normal" htmlFor="privacy1">
|
||||
On Phoenix, our distribution partners, and search engines,{' '}
|
||||
<br />
|
||||
anybody can find the event
|
||||
</Form.Check.Label>
|
||||
</Form.Check>
|
||||
<Form.Check type="radio" id="privacy2" className="mb-0">
|
||||
<Form.Check.Input
|
||||
type="radio"
|
||||
name="vrivacyRadio"
|
||||
value="option1"
|
||||
/>
|
||||
<Form.Check.Label className="fw-normal" htmlFor="privacy2">
|
||||
Only the individuals you select have access to it.
|
||||
</Form.Check.Label>
|
||||
</Form.Check>
|
||||
</div>
|
||||
<div className="border-bottom border-translucent mb-6">
|
||||
<Form.Check type="checkbox" id="flexChecked">
|
||||
<Form.Check.Input
|
||||
type="checkbox"
|
||||
value="option1"
|
||||
defaultChecked
|
||||
/>
|
||||
<Form.Check.Label
|
||||
className="fw-bold fs-8 mb-5"
|
||||
htmlFor="flexChecked"
|
||||
>
|
||||
Show the number of available tickets
|
||||
</Form.Check.Label>
|
||||
</Form.Check>
|
||||
</div>
|
||||
<EventTicketPricing />
|
||||
<EventCustomFields />
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateAnEvent;
|
||||
71
src/pages/apps/events/EventDetail.tsx
Normal file
71
src/pages/apps/events/EventDetail.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import coverImg from 'assets/img/generic/34.png';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import EventTitleCard from 'components/cards/EventTitleCard';
|
||||
import ResponsesAndShare from 'components/modules/events/ResponsesAndShare';
|
||||
import Location from 'components/modules/events/Location';
|
||||
import Badge from 'components/base/Badge';
|
||||
import Events from 'components/modules/events/Events';
|
||||
import EventsSingersSection from 'components/modules/events/EventsSingersSection';
|
||||
import EventsTopicCovered from 'components/list-items/EventsTopicCovered';
|
||||
import EventsOrganized from 'components/modules/events/EventsOrganized';
|
||||
import { SingerPhotos, events } from 'data/eventsData';
|
||||
|
||||
const EventDetail = () => {
|
||||
return (
|
||||
<div className="pb-9">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<h2 className="mb-4 mb-lg-6">Event details</h2>
|
||||
<img
|
||||
src={coverImg}
|
||||
alt=""
|
||||
className="rounded w-100 fit-cover mb-5 mb-md-6 mb-xl-8"
|
||||
style={{ minHeight: '250px' }}
|
||||
/>
|
||||
<Row className="gx-lg-9">
|
||||
<Col xl={8} className="border-end-xl">
|
||||
<EventTitleCard className="mb-9" />
|
||||
<h2 className="mb-3">About this event</h2>
|
||||
<p className="text-justify text-body-secondary mb-6 mb-xxl-8">
|
||||
The Festival Season hopes to continue its rescheduled events in 2023
|
||||
during the spring block. This will be a continuation of the
|
||||
tradition for the loyal fanbase to watch a jam-packed day full of
|
||||
exciting top-notch performances. With a unique lineup, you’ll know
|
||||
what to expect and get ready to embrace the festivity. Moreover,
|
||||
we’ve added a detailed list of the performers, with details of
|
||||
dates, lineups and prospective entry requirements. We will keep you
|
||||
posted with necessary updates regarding the event.
|
||||
</p>
|
||||
<EventsSingersSection photos={SingerPhotos} />
|
||||
<EventsTopicCovered />
|
||||
<h4 className="mb-3 text-body-highlight fs-xxl-6">Refund Policy:</h4>
|
||||
<ul className="mb-6 ps-4">
|
||||
<li>Contact the organizer to request a refund.</li>
|
||||
<li>Eventbrite’s fee is nonrefundable.</li>
|
||||
</ul>
|
||||
<ResponsesAndShare />
|
||||
</Col>
|
||||
<Col xl={4}>
|
||||
<EventsOrganized />
|
||||
<Location />
|
||||
<h3 className="mb-3">Tags</h3>
|
||||
<div className="d-flex flex-wrap mb-8">
|
||||
<Badge variant="tag" className="me-2">
|
||||
Music
|
||||
</Badge>
|
||||
<Badge variant="tag" className="me-2">
|
||||
CONCERT
|
||||
</Badge>
|
||||
<Badge variant="tag">Greatest show on earth</Badge>
|
||||
</div>
|
||||
<div className="border-top border-translucent">
|
||||
<Events events={events} title="Upcoming events" />
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EventDetail;
|
||||
117
src/pages/apps/kanban/Boards.tsx
Normal file
117
src/pages/apps/kanban/Boards.tsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import {
|
||||
faAnglesDown,
|
||||
faBoxArchive,
|
||||
faCalendarXmark,
|
||||
faFilter,
|
||||
faPlus
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import SearchBox from 'components/common/SearchBox';
|
||||
import { privateBoards, recentBoards, yourBoards } from 'data/kanban';
|
||||
import { useMainLayoutContext } from 'providers/MainLayoutProvider';
|
||||
import { useEffect } from 'react';
|
||||
import { Col, Form, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import KanbanBoardSection from 'components/modules/kanban/KanbanBoardSection';
|
||||
|
||||
const Boards = () => {
|
||||
const { setContentClass } = useMainLayoutContext();
|
||||
|
||||
useEffect(() => {
|
||||
setContentClass('kanban-boards-content');
|
||||
|
||||
return () => {
|
||||
setContentClass('');
|
||||
};
|
||||
}, []);
|
||||
return (
|
||||
<div className="mb-9">
|
||||
<div className="border-bottom border-translucent px-4 px-lg-6 pb-5">
|
||||
<Row className="justify-content-between gy-4">
|
||||
<Col xs="auto">
|
||||
<h2>
|
||||
Kanban Boards{' '}
|
||||
<span className="text-body-tertiary fw-semibold">(8)</span>
|
||||
</h2>
|
||||
</Col>
|
||||
<Col xs="auto" className="d-flex flex-wrap gap-2">
|
||||
<Button
|
||||
variant="phoenix-primary"
|
||||
startIcon={<FontAwesomeIcon icon={faFilter} />}
|
||||
className="d-flex px-4"
|
||||
>
|
||||
Filter
|
||||
</Button>
|
||||
<Form.Select className="w-auto" id="select-deals">
|
||||
<option>Sort by - Last visited</option>
|
||||
<option>Sort by - Name (A - Z)</option>
|
||||
<option>Sort by - Name (Z - A)</option>
|
||||
<option>Sort by - Category</option>
|
||||
<option>Sort by - Date created</option>
|
||||
</Form.Select>
|
||||
<SearchBox placeholder="Search by name" />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<div className="d-flex flex-wrap gap-3 border-bottom border-translucent px-4 px-lg-6 py-5">
|
||||
<Button
|
||||
variant="primary"
|
||||
className="px-3 px-sm-5 px-md-10"
|
||||
as={Link}
|
||||
to="/apps/kanban/create-board"
|
||||
startIcon={<FontAwesomeIcon icon={faPlus} className="me-2" />}
|
||||
>
|
||||
Create New Board
|
||||
</Button>
|
||||
<Button
|
||||
variant="phoenix-primary"
|
||||
className="px-3 px-sm-4 d-flex text-body"
|
||||
as={Link}
|
||||
to="#!"
|
||||
>
|
||||
<FontAwesomeIcon icon={faAnglesDown} className="me-sm-2" />
|
||||
<span className="d-none d-sm-block white-space-nowrap">
|
||||
Import Bulk Tasks
|
||||
</span>
|
||||
</Button>
|
||||
<Button
|
||||
variant="phoenix-primary"
|
||||
className="px-3 px-sm-4 d-flex text-body"
|
||||
as={Link}
|
||||
to="#!"
|
||||
>
|
||||
<FontAwesomeIcon icon={faCalendarXmark} className="me-sm-2" />
|
||||
<span className="d-none d-sm-block">Upcoming Deadlines</span>
|
||||
</Button>
|
||||
</div>
|
||||
<KanbanBoardSection
|
||||
title="Most Recent Boards"
|
||||
description="Boards you’ve visited recently. Can be private or public boards."
|
||||
changePreference={true}
|
||||
boards={recentBoards}
|
||||
/>
|
||||
<KanbanBoardSection
|
||||
title="Your Boards"
|
||||
description="Boards where you are either an Admin or a Member."
|
||||
boards={yourBoards}
|
||||
/>
|
||||
<KanbanBoardSection
|
||||
title="Private Boards"
|
||||
description="Your eyes only"
|
||||
boards={privateBoards}
|
||||
/>
|
||||
<div className="text-center">
|
||||
<Button
|
||||
variant="phoenix-primary"
|
||||
startIcon={<FontAwesomeIcon icon={faBoxArchive} className="me-2" />}
|
||||
className="mt-4"
|
||||
>
|
||||
Open Archive
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Boards;
|
||||
47
src/pages/apps/kanban/CreateBoard.tsx
Normal file
47
src/pages/apps/kanban/CreateBoard.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import boardIcon from 'assets/img/kanban/board.png';
|
||||
import boardIllustration from 'assets/img/kanban/board-light.png';
|
||||
import boardIllustrationDark from 'assets/img/kanban/board-dark.png';
|
||||
import CreateBoardWizardForm from 'components/modules/kanban/create-board/CreateBoardWizardForm';
|
||||
|
||||
const CreateBoard = () => {
|
||||
return (
|
||||
<div className="mb-9">
|
||||
<div className="mb-xl-8">
|
||||
<div className="d-flex align-items-center mb-3">
|
||||
<img src={boardIcon} alt="" className="me-3" />
|
||||
<h1 className="mb-0 text-body-emphasis fw-semibold">
|
||||
Phoenix Kanban
|
||||
</h1>
|
||||
</div>
|
||||
<p className="mb-0">
|
||||
Create a Kanban board by following the steps below
|
||||
</p>
|
||||
</div>
|
||||
<Row className="kanban-create-board">
|
||||
<Col
|
||||
xs={12}
|
||||
xl={6}
|
||||
xxl={7}
|
||||
className="text-center kanban-board-bg order-xl-1"
|
||||
>
|
||||
<img
|
||||
src={boardIllustration}
|
||||
alt=""
|
||||
className="d-dark-none mt-5 mb-6 mb-xl-0 position-sticky"
|
||||
/>
|
||||
<img
|
||||
src={boardIllustrationDark}
|
||||
alt=""
|
||||
className="d-light-none mt-5 mb-6 mb-xl-0 position-sticky"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} xl={6} xxl={5}>
|
||||
<CreateBoardWizardForm />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateBoard;
|
||||
199
src/pages/apps/kanban/Kanban.tsx
Normal file
199
src/pages/apps/kanban/Kanban.tsx
Normal file
@@ -0,0 +1,199 @@
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import KanbanAddListModal from 'components/modals/KanbanAddListModal';
|
||||
import KanbanBoardOffcanvas from 'components/modules/kanban/KanbanBoardOffcanvas';
|
||||
import KanbanHeader from 'components/modules/kanban/KanbanHeader';
|
||||
import KanbanList from 'components/modules/kanban/KanbanList';
|
||||
import KanbanProvider, { useKanbanContext } from 'providers/KanbanProvider';
|
||||
import { useMainLayoutContext } from 'providers/MainLayoutProvider';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { TOGGLE_ADD_LIST_MODAL } from 'reducers/KanbanReducer';
|
||||
import { KanbanBoardItem, KanbanBoardTask } from 'data/kanban';
|
||||
import {
|
||||
DndContext,
|
||||
DragOverlay,
|
||||
DragStartEvent,
|
||||
DragOverEvent,
|
||||
DragEndEvent,
|
||||
closestCorners
|
||||
} from '@dnd-kit/core';
|
||||
import { arrayMove } from '@dnd-kit/sortable';
|
||||
import KanbanListItemCard from 'components/modules/kanban/KanbanListItemCard';
|
||||
import { useGetDndSensor } from 'hooks/useGetDndSensor';
|
||||
|
||||
const Kanban = () => {
|
||||
const { setContentClass } = useMainLayoutContext();
|
||||
|
||||
useEffect(() => {
|
||||
setContentClass('kanban-content');
|
||||
|
||||
return () => {
|
||||
setContentClass('');
|
||||
};
|
||||
}, [setContentClass]);
|
||||
|
||||
return (
|
||||
<KanbanProvider>
|
||||
<KanbanContent />
|
||||
</KanbanProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const KanbanContent = () => {
|
||||
const { boardLists, kanbanDispatch } = useKanbanContext();
|
||||
const sensors = useGetDndSensor();
|
||||
const [activeTask, setActiveTask] = useState<KanbanBoardTask | null>(null);
|
||||
const [activeList, setActiveList] = useState<KanbanBoardItem | null>(null);
|
||||
const findColumn = (id: number) => {
|
||||
return boardLists.find(
|
||||
col => col.tasks.some(task => task.id === id) || col.id === id
|
||||
);
|
||||
};
|
||||
|
||||
const handleDragStart = (event: DragStartEvent) => {
|
||||
const { active } = event;
|
||||
|
||||
const activeColumn = boardLists.find(
|
||||
list => list.id === active.data.current?.columnId
|
||||
);
|
||||
setActiveTask(active.data.current?.item);
|
||||
setActiveList(activeColumn || null);
|
||||
};
|
||||
|
||||
const handleDragOver = (event: DragOverEvent) => {
|
||||
const { active, over } = event;
|
||||
if (!active || !over) return;
|
||||
|
||||
const activeId = Number(active.id);
|
||||
const overId = Number(over.id);
|
||||
|
||||
const activeColumn = findColumn(activeId);
|
||||
const overColumn = findColumn(overId);
|
||||
|
||||
if (!activeColumn || !overColumn || activeColumn.id === overColumn.id)
|
||||
return;
|
||||
|
||||
const activeTaskIndex = activeColumn.tasks.findIndex(
|
||||
task => task.id === activeId
|
||||
);
|
||||
const overTaskIndex = overColumn.tasks.findIndex(
|
||||
task => task.id === overId
|
||||
);
|
||||
|
||||
const updatedSourceTasks = activeColumn.tasks.filter(
|
||||
task => task.id !== activeId
|
||||
);
|
||||
const updatedDestTasks = [
|
||||
...overColumn.tasks.slice(0, overTaskIndex + 1),
|
||||
activeColumn.tasks[activeTaskIndex],
|
||||
...overColumn.tasks.slice(overTaskIndex + 1)
|
||||
];
|
||||
|
||||
kanbanDispatch({
|
||||
type: 'UPDATE_DUAL_COLUMN',
|
||||
payload: {
|
||||
sourceColumn: activeColumn,
|
||||
updatedSourceItems: updatedSourceTasks,
|
||||
destColumn: overColumn,
|
||||
updatedDestItems: updatedDestTasks
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleDragEnd = (event: DragEndEvent) => {
|
||||
const { active, over } = event;
|
||||
if (!active || !over) return;
|
||||
|
||||
const activeId = Number(active.id);
|
||||
const overId = Number(over.id);
|
||||
|
||||
const activeColumn = findColumn(activeId);
|
||||
const overColumn = findColumn(overId);
|
||||
|
||||
if (!activeColumn || !overColumn) return;
|
||||
|
||||
if (activeColumn.id === overColumn.id) {
|
||||
const oldIndex = activeColumn.tasks.findIndex(
|
||||
task => task.id === activeId
|
||||
);
|
||||
const newIndex = activeColumn.tasks.findIndex(task => task.id === overId);
|
||||
|
||||
if (oldIndex === -1 || newIndex === -1) return;
|
||||
|
||||
const reorderedTasks = arrayMove(activeColumn.tasks, oldIndex, newIndex);
|
||||
|
||||
kanbanDispatch({
|
||||
type: 'UPDATE_SINGLE_COLUMN',
|
||||
payload: { column: activeColumn, reorderItems: reorderedTasks }
|
||||
});
|
||||
} else {
|
||||
const activeTask = activeColumn.tasks.find(task => task.id === activeId);
|
||||
|
||||
if (!activeTask) return;
|
||||
|
||||
const updatedSourceTasks = activeColumn.tasks.filter(
|
||||
task => task.id !== activeId
|
||||
);
|
||||
const updatedDestTasks = [...overColumn.tasks, activeTask];
|
||||
|
||||
kanbanDispatch({
|
||||
type: 'UPDATE_DUAL_COLUMN',
|
||||
payload: {
|
||||
sourceColumn: activeColumn,
|
||||
updatedSourceItems: updatedSourceTasks,
|
||||
destColumn: overColumn,
|
||||
updatedDestItems: updatedDestTasks
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setActiveTask(null);
|
||||
setActiveList(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCorners}
|
||||
onDragStart={handleDragStart}
|
||||
onDragOver={handleDragOver}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<div>
|
||||
<KanbanHeader />
|
||||
<div className="kanban-container scrollbar">
|
||||
{boardLists.map(list => (
|
||||
<KanbanList list={list} key={list.id} columnId={list.id} />
|
||||
))}
|
||||
<div className="kanban-column scrollbar position-relative bg-transparent d-flex flex-column h-100 flex-center bg-body-hover">
|
||||
<Button
|
||||
className="stretched-link btn-icon btn-icon bg-body-secondary rounded-circle mb-1"
|
||||
onClick={() =>
|
||||
kanbanDispatch({
|
||||
type: TOGGLE_ADD_LIST_MODAL,
|
||||
payload: true
|
||||
})
|
||||
}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faPlus}
|
||||
className="text-body-secondary fs-8"
|
||||
/>
|
||||
</Button>
|
||||
<h5 className="text-body-secondary">Add another list</h5>
|
||||
</div>
|
||||
</div>
|
||||
<KanbanBoardOffcanvas />
|
||||
<KanbanAddListModal />
|
||||
</div>
|
||||
<DragOverlay className="drag-overlay">
|
||||
{activeList && activeTask && (
|
||||
<KanbanListItemCard list={activeList} task={activeTask} />
|
||||
)}
|
||||
</DragOverlay>
|
||||
</DndContext>
|
||||
);
|
||||
};
|
||||
|
||||
export default Kanban;
|
||||
184
src/pages/apps/project-management/CreateNew.tsx
Normal file
184
src/pages/apps/project-management/CreateNew.tsx
Normal file
@@ -0,0 +1,184 @@
|
||||
import Button from 'components/base/Button';
|
||||
import DatePicker from 'components/base/DatePicker';
|
||||
import ReactSelect from 'components/base/ReactSelect';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Col, FloatingLabel, Form, Row } from 'react-bootstrap';
|
||||
|
||||
const CreateNew = () => {
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<h2 className="mb-4">Create a project</h2>
|
||||
<Row>
|
||||
<Col xs={12} xl={9}>
|
||||
<Row as="form" className="g-3 mb-6">
|
||||
<Col sm={6} md={8}>
|
||||
<FloatingLabel
|
||||
controlId="floatingInputGrid"
|
||||
label="Project title"
|
||||
>
|
||||
<Form.Control type="text" placeholder="Project title" />
|
||||
</FloatingLabel>
|
||||
</Col>
|
||||
<Col sm={6} md={4}>
|
||||
<FloatingLabel
|
||||
controlId="floatingSelectTask"
|
||||
label="Defult task view"
|
||||
>
|
||||
<Form.Select>
|
||||
<option>Select task view</option>
|
||||
<option value="1">technical</option>
|
||||
<option value="2">external</option>
|
||||
<option value="3">organizational</option>
|
||||
</Form.Select>
|
||||
</FloatingLabel>
|
||||
</Col>
|
||||
<Col sm={6} md={4}>
|
||||
<FloatingLabel
|
||||
controlId="floatingSelectPrivacy"
|
||||
label="Project privacy"
|
||||
>
|
||||
<Form.Select>
|
||||
<option>Select privacy</option>
|
||||
<option value="1">Data Privacy One</option>
|
||||
<option value="2">Data Privacy Two</option>
|
||||
<option value="3">Data Privacy Three</option>
|
||||
</Form.Select>
|
||||
</FloatingLabel>
|
||||
</Col>
|
||||
<Col sm={6} md={4}>
|
||||
<FloatingLabel controlId="floatingSelectTeam" label="Team">
|
||||
<Form.Select>
|
||||
<option>Select team</option>
|
||||
<option value="1">Team One</option>
|
||||
<option value="2">Team Two</option>
|
||||
<option value="3">Team Three</option>
|
||||
</Form.Select>
|
||||
</FloatingLabel>
|
||||
</Col>
|
||||
<Col sm={6} md={4}>
|
||||
<FloatingLabel controlId="floatingSelectAssignees" label="People">
|
||||
<Form.Select>
|
||||
<option>Select assignees</option>
|
||||
<option value="1">One</option>
|
||||
<option value="2">Two</option>
|
||||
<option value="3">Three</option>
|
||||
</Form.Select>
|
||||
</FloatingLabel>
|
||||
</Col>
|
||||
<Col sm={6} md={4}>
|
||||
<FloatingLabel
|
||||
controlId="floatingSelectAdmin"
|
||||
label="Project Lead"
|
||||
>
|
||||
<Form.Select>
|
||||
<option>Select admin</option>
|
||||
<option value="1">Data Privacy One</option>
|
||||
<option value="2">Data Privacy Two</option>
|
||||
<option value="3">Data Privacy Three</option>
|
||||
</Form.Select>
|
||||
</FloatingLabel>
|
||||
</Col>
|
||||
<Col sm={6} md={4}>
|
||||
<DatePicker
|
||||
render={(_, ref) => {
|
||||
return (
|
||||
<Form.Floating>
|
||||
<Form.Control
|
||||
type="text"
|
||||
placeholder="Project title"
|
||||
ref={ref}
|
||||
id="startDate"
|
||||
/>
|
||||
<label htmlFor="startDate" className="ps-6">
|
||||
Start date
|
||||
</label>
|
||||
</Form.Floating>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col sm={6} md={4}>
|
||||
<DatePicker
|
||||
render={(_, ref) => {
|
||||
return (
|
||||
<Form.Floating>
|
||||
<Form.Control
|
||||
type="date"
|
||||
placeholder="Deadline"
|
||||
ref={ref}
|
||||
id="deadline"
|
||||
/>
|
||||
<label htmlFor="deadline" className="ps-6">
|
||||
Deadline
|
||||
</label>
|
||||
</Form.Floating>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} className="gy-6">
|
||||
<FloatingLabel
|
||||
controlId="floatingProjectOverview"
|
||||
label="Project overview"
|
||||
>
|
||||
<Form.Control
|
||||
as="textarea"
|
||||
placeholder="Leave a comment here"
|
||||
style={{ height: '100px' }}
|
||||
/>
|
||||
</FloatingLabel>
|
||||
</Col>
|
||||
<Col md={6} className="gy-6">
|
||||
<FloatingLabel controlId="floatingSelectClient" label="Client">
|
||||
<Form.Select>
|
||||
<option>Select client</option>
|
||||
<option value="1">Client One</option>
|
||||
<option value="2">Client Two</option>
|
||||
<option value="3">Client Three</option>
|
||||
</Form.Select>
|
||||
</FloatingLabel>
|
||||
</Col>
|
||||
<Col md={6} className="gy-6">
|
||||
<FloatingLabel controlId="floatingInputBudget" label="Budget">
|
||||
<Form.Control type="text" placeholder="Budget" />
|
||||
</FloatingLabel>
|
||||
</Col>
|
||||
<Col xs={12} className="gy-6">
|
||||
<ReactSelect
|
||||
isMulti
|
||||
placeholder="Add tags"
|
||||
options={[
|
||||
{ value: 'Biology', label: 'Biology' },
|
||||
{ value: 'Brainlessness', label: 'Brainlessness' },
|
||||
{ value: 'Jerry', label: 'Jerry' },
|
||||
{ value: 'Neurology', label: 'Neurology' },
|
||||
{ value: 'Not_the_mouse', label: 'Not_the_mouse' },
|
||||
{ value: 'Rick', label: 'Rick' },
|
||||
{ value: 'Stupidity', label: 'Stupidity' }
|
||||
]}
|
||||
classNames={{
|
||||
control: () => 'py-3',
|
||||
valueContainer: () => 'lh-1'
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} className="gy-6">
|
||||
<div className="d-flex justify-content-end gap-3">
|
||||
<Button variant="phoenix-primary" className="px-5">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="primary" className="px-5 px-sm-15">
|
||||
Create Project
|
||||
</Button>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateNew;
|
||||
70
src/pages/apps/project-management/ProjectBoardView.tsx
Normal file
70
src/pages/apps/project-management/ProjectBoardView.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { ColumnDef } from '@tanstack/react-table';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import ProjectsTopSection from 'components/modules/project-management/ProjectsTopSection';
|
||||
import BoardViewItem from 'components/modules/project-management/board-view/BoardViewItem';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Project, projects } from 'data/project-management/projects';
|
||||
import useAdvanceTable from 'hooks/useAdvanceTable';
|
||||
import AdvanceTableProvider from 'providers/AdvanceTableProvider';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export const columns: ColumnDef<Project>[] = [
|
||||
{
|
||||
// For filtering and searching projects by status
|
||||
id: 'status',
|
||||
accessorFn: ({ status }) => status.label
|
||||
},
|
||||
{
|
||||
// For searching projects by name
|
||||
accessorKey: 'name'
|
||||
}
|
||||
];
|
||||
|
||||
const ProjectBoardView = () => {
|
||||
const table = useAdvanceTable<Project>({
|
||||
data: projects,
|
||||
columns,
|
||||
pageSize: 10,
|
||||
pagination: true,
|
||||
sortable: true
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<AdvanceTableProvider {...table}>
|
||||
<div className="d-flex flex-wrap mb-4 gap-3 gap-sm-6 align-items-center">
|
||||
<h2 className="mb-0">
|
||||
<span className="me-3">Projects</span>{' '}
|
||||
<span className="fw-normal text-body-tertiary">
|
||||
({projects.length})
|
||||
</span>
|
||||
</h2>
|
||||
<Link
|
||||
className="btn btn-primary px-5"
|
||||
to="/apps/project-management/create-new"
|
||||
>
|
||||
<FontAwesomeIcon icon={faPlus} className="me-2" />
|
||||
Add new project
|
||||
</Link>
|
||||
</div>
|
||||
<ProjectsTopSection activeView="board" />
|
||||
<Row className="g-3 mb-9">
|
||||
{table
|
||||
.getRowModel()
|
||||
.rows.map(row => row.original)
|
||||
.map(project => (
|
||||
<Col xs={12} sm={6} md={4} xxl={3} key={project.id}>
|
||||
<BoardViewItem project={project} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</AdvanceTableProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectBoardView;
|
||||
70
src/pages/apps/project-management/ProjectCardView.tsx
Normal file
70
src/pages/apps/project-management/ProjectCardView.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { ColumnDef } from '@tanstack/react-table';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import ProjectsTopSection from 'components/modules/project-management/ProjectsTopSection';
|
||||
import CardViewItem from 'components/modules/project-management/card-view/CardViewItem';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Project, projects } from 'data/project-management/projects';
|
||||
import useAdvanceTable from 'hooks/useAdvanceTable';
|
||||
import AdvanceTableProvider from 'providers/AdvanceTableProvider';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export const columns: ColumnDef<Project>[] = [
|
||||
{
|
||||
// For filtering and searching projects by status
|
||||
id: 'status',
|
||||
accessorFn: ({ status }) => status.label
|
||||
},
|
||||
{
|
||||
// For searching projects by name
|
||||
accessorKey: 'name'
|
||||
}
|
||||
];
|
||||
|
||||
const ProjectCardView = () => {
|
||||
const table = useAdvanceTable<Project>({
|
||||
data: projects,
|
||||
columns,
|
||||
pageSize: 10,
|
||||
pagination: true,
|
||||
sortable: true
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<AdvanceTableProvider {...table}>
|
||||
<div className="d-flex flex-wrap mb-4 gap-3 gap-sm-6 align-items-center">
|
||||
<h2 className="mb-0">
|
||||
<span className="me-3">Projects</span>{' '}
|
||||
<span className="fw-normal text-body-tertiary">
|
||||
({projects.length})
|
||||
</span>
|
||||
</h2>
|
||||
<Link
|
||||
className="btn btn-primary px-5"
|
||||
to="/apps/project-management/create-new"
|
||||
>
|
||||
<FontAwesomeIcon icon={faPlus} className="me-2" />
|
||||
Add new project
|
||||
</Link>
|
||||
</div>
|
||||
<ProjectsTopSection activeView="card" />
|
||||
<Row className="g-3 mb-9">
|
||||
{table
|
||||
.getRowModel()
|
||||
.rows.map(row => row.original)
|
||||
.map(project => (
|
||||
<Col xs={12} sm={6} xl={4} xxl={3} key={project.id}>
|
||||
<CardViewItem project={project} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</AdvanceTableProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectCardView;
|
||||
140
src/pages/apps/project-management/ProjectDetails.tsx
Normal file
140
src/pages/apps/project-management/ProjectDetails.tsx
Normal file
@@ -0,0 +1,140 @@
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { UilStopwatch } from '@iconscout/react-unicons';
|
||||
import classNames from 'classnames';
|
||||
import Badge from 'components/base/Badge';
|
||||
import Button from 'components/base/Button';
|
||||
import RevealDropdown, {
|
||||
RevealDropdownTrigger
|
||||
} from 'components/base/RevealDropdown';
|
||||
import ProjectDetailsSummary from 'components/modules/project-management/project-details/ProjectDetailsSummary';
|
||||
import TaskCompleted from 'components/modules/project-management/project-details/TaskCompleted';
|
||||
import TeamMembers from 'components/modules/project-management/project-details/TeamMembers';
|
||||
import WorkLoads from 'components/modules/project-management/project-details/WorkLoads';
|
||||
import FileListItem from 'components/modules/project-management/todo-list/FileListItem';
|
||||
import ActivityTimeline from 'components/timelines/ActivityTimeline';
|
||||
import { activityTimelineData } from 'data/project-management/activityTimelineData';
|
||||
import { attachments } from 'data/project-management/todoListData';
|
||||
import { useMainLayoutContext } from 'providers/MainLayoutProvider';
|
||||
import { useEffect } from 'react';
|
||||
import { Col, Dropdown, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const ProjectDetails = () => {
|
||||
const { setContentClass } = useMainLayoutContext();
|
||||
|
||||
useEffect(() => {
|
||||
setContentClass('px-0 pt-navbar');
|
||||
|
||||
return () => {
|
||||
setContentClass('');
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Row className="g-0">
|
||||
<Col xs={12} xxl={8} className="px-0 bg-body">
|
||||
<div className="px-4 px-lg-6 pt-6 pb-9">
|
||||
<div className="mb-5">
|
||||
<div className="d-flex justify-content-between">
|
||||
<h2 className="text-body-emphasis fw-bolder mb-2">
|
||||
Retrieving Old Repos to Redirect to a new URL
|
||||
</h2>
|
||||
<RevealDropdownTrigger>
|
||||
<RevealDropdown>
|
||||
<Dropdown.Item>Edit</Dropdown.Item>
|
||||
<Dropdown.Item className="text-danger">Delete</Dropdown.Item>
|
||||
<Dropdown.Item>Downlaod</Dropdown.Item>
|
||||
<Dropdown.Item>Report abuse</Dropdown.Item>
|
||||
</RevealDropdown>
|
||||
</RevealDropdownTrigger>
|
||||
</div>
|
||||
<Badge
|
||||
variant="phoenix"
|
||||
bg="primary"
|
||||
iconPosition="end"
|
||||
icon={<UilStopwatch size={12} className="ms-1" />}
|
||||
>
|
||||
Ongoing
|
||||
</Badge>
|
||||
</div>
|
||||
<Row className="gx-0 gx-sm-5 gy-8 mb-8">
|
||||
<Col xs={12} xl={3} xxl={4} className="pe-xl-0">
|
||||
<ProjectDetailsSummary />
|
||||
</Col>
|
||||
<Col xs={12} xl={9} xxl={8}>
|
||||
<TaskCompleted />
|
||||
</Col>
|
||||
<Col xs={12} sm={5} lg={4} xl={3} xxl={4}>
|
||||
<WorkLoads />
|
||||
</Col>
|
||||
<Col xs={12} sm={7} lg={8} xl={5}>
|
||||
<TeamMembers />
|
||||
</Col>
|
||||
</Row>
|
||||
<div>
|
||||
<h3 className="text-body-emphasis mb-4">Project overview</h3>
|
||||
<p className="text-body-secondary mb-4">
|
||||
The new redirection team is happy to announce that we’ve fixed all
|
||||
our unresponsive URLs and redirected them to new URLs. The
|
||||
tremendous assistance from our support team and the dev team, as
|
||||
well as that of the team lead’s, this team has made an impossible
|
||||
possible within a week. They didn’t stop for a moment, and we got
|
||||
our pages working again for all the valuable users.{' '}
|
||||
</p>
|
||||
<p className="text-body-secondary mb-0">
|
||||
Join us in celebrating the massive success of data transferring
|
||||
and getting us a huge revenue by eating out. Free public viewing
|
||||
and a buffet is offered for the great team as well as for the
|
||||
other teams working with us. We’ll be checking out places for the
|
||||
best option available at hands and we’ll let you know the schedule
|
||||
once we decide on one...
|
||||
<Link className="fw-semibold" to="#!">
|
||||
read more
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
<Col xs={12} xxl={4} className="px-0 border-start-xxl">
|
||||
<div className="h-100">
|
||||
<div className="bg-light dark__bg-gray-1100 h-100">
|
||||
<div className="p-4 p-lg-6">
|
||||
<h3 className="text-body-highlight mb-4 fw-bold">
|
||||
Recent activity
|
||||
</h3>
|
||||
<ActivityTimeline data={activityTimelineData} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="px-4 px-lg-6 mb-3">
|
||||
<h4 className="mb-0">Files</h4>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
{attachments.map((attachment, index) => (
|
||||
<FileListItem
|
||||
key={attachment.name}
|
||||
attachment={attachment}
|
||||
className={classNames('px-4 px-lg-6', {
|
||||
'border-top': index === 0
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="px-5 px-md-6 mb-9">
|
||||
<Button
|
||||
variant="link"
|
||||
className="text-decoration-none p-0"
|
||||
startIcon={<FontAwesomeIcon icon={faPlus} className="me-1" />}
|
||||
>
|
||||
Add file(s)
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectDetails;
|
||||
46
src/pages/apps/project-management/ProjectListView.tsx
Normal file
46
src/pages/apps/project-management/ProjectListView.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import ProjectsTopSection from 'components/modules/project-management/ProjectsTopSection';
|
||||
import ProjectListTable, {
|
||||
projectListTableColumns
|
||||
} from 'components/tables/ProjectListTable';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { projects } from 'data/project-management/projects';
|
||||
import useAdvanceTable from 'hooks/useAdvanceTable';
|
||||
import AdvanceTableProvider from 'providers/AdvanceTableProvider';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const ProjectListView = () => {
|
||||
const table = useAdvanceTable({
|
||||
data: projects,
|
||||
columns: projectListTableColumns,
|
||||
pageSize: 6,
|
||||
pagination: true,
|
||||
sortable: true
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<AdvanceTableProvider {...table}>
|
||||
<div className="d-flex flex-wrap mb-4 gap-3 gap-sm-6 align-items-center">
|
||||
<h2 className="mb-0">
|
||||
<span className="me-3">Projects</span>{' '}
|
||||
<span className="fw-normal text-body-tertiary">
|
||||
({projects.length})
|
||||
</span>
|
||||
</h2>
|
||||
<Link className="btn btn-primary px-5" to="/">
|
||||
<FontAwesomeIcon icon={faPlus} className="me-2" />
|
||||
Add new project
|
||||
</Link>
|
||||
</div>
|
||||
<ProjectsTopSection activeView="list" />
|
||||
<ProjectListTable />
|
||||
</AdvanceTableProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectListView;
|
||||
76
src/pages/apps/project-management/ProjectTodoList.tsx
Normal file
76
src/pages/apps/project-management/ProjectTodoList.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import { faFilter, faPlus, faSort } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import classNames from 'classnames';
|
||||
import Button from 'components/base/Button';
|
||||
import SearchBox from 'components/common/SearchBox';
|
||||
import TodoItemDetailsOffcanvas from 'components/modules/project-management/todo-list/TodoItemDetailsOffcanvas';
|
||||
import TodoListItem from 'components/modules/project-management/todo-list/TodoListItem';
|
||||
import { ToDoItem, todoList } from 'data/project-management/todoListData';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
const ProjectTodoList = () => {
|
||||
const [selectedItem, setSelectedItem] = useState<ToDoItem | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedItem) {
|
||||
document.body.style.overflow = 'hidden';
|
||||
} else {
|
||||
document.body.style.overflow = 'auto';
|
||||
}
|
||||
}, [selectedItem]);
|
||||
|
||||
return (
|
||||
<div className="mb-9">
|
||||
<h2 className="mb-4">
|
||||
Todo list<span className="text-body-tertiary fw-normal">(23)</span>
|
||||
</h2>
|
||||
<div className="d-flex align-items-center flex-wrap gap-x-5 gap-y-3 mb-3">
|
||||
<SearchBox placeholder="Search tasks" style={{ maxWidth: '30rem' }} />
|
||||
<div>
|
||||
<Button
|
||||
variant="link"
|
||||
className="p-0 fs-9 text-body-tertiary text-decoration-none me-3"
|
||||
startIcon={
|
||||
<FontAwesomeIcon icon={faFilter} className="fs-10 me-1" />
|
||||
}
|
||||
>
|
||||
23 tasks
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
className="p-0 fs-9 text-primary text-decoration-none"
|
||||
startIcon={<FontAwesomeIcon icon={faSort} className="fs-10" />}
|
||||
>
|
||||
Sorting
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="todolist-container ms-n1 ps-1 scrollbar">
|
||||
{todoList.map((todo, index) => (
|
||||
<TodoListItem
|
||||
key={todo.task}
|
||||
todo={todo}
|
||||
className={classNames({
|
||||
'border-top': index === 0
|
||||
})}
|
||||
fullLayoutBreakpoints={['md']}
|
||||
onClick={item => setSelectedItem(item)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
startIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
variant="link"
|
||||
className="text-decoration-none p-0 mt-4"
|
||||
>
|
||||
Add new task
|
||||
</Button>
|
||||
<TodoItemDetailsOffcanvas
|
||||
handleClose={() => setSelectedItem(null)}
|
||||
item={selectedItem}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectTodoList;
|
||||
57
src/pages/apps/social/Feed.tsx
Normal file
57
src/pages/apps/social/Feed.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import SocialProfileCard from 'components/cards/SocialProfileCard';
|
||||
import Events from 'components/modules/events/Events';
|
||||
import NavbarBottom from 'components/modules/social/NavbarBottom';
|
||||
import SocialMessages from 'components/list-items/SocialMessages';
|
||||
import SocialPhotos from 'components/image-gallery/SocialPhotos';
|
||||
import SocialPosts from 'components/modules/social/SocialPosts';
|
||||
import { events } from 'data/eventsData';
|
||||
import { messages } from 'data/social/messages';
|
||||
import { feedPosts, socialPhotos } from 'data/social/postsData';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import ProfileNavigation from 'components/list-items/ProfileNavigation';
|
||||
import FeedTextarea from 'components/forms/FeedTextarea';
|
||||
import { useMainLayoutContext } from 'providers/MainLayoutProvider';
|
||||
import { useEffect } from 'react';
|
||||
import profileImage from 'assets/img/team/59.webp';
|
||||
|
||||
const Feed = () => {
|
||||
const { setFooterClass } = useMainLayoutContext();
|
||||
|
||||
useEffect(() => {
|
||||
setFooterClass('d-none d-lg-block');
|
||||
return () => {
|
||||
setFooterClass('');
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-9">
|
||||
<Row className="gy-3 gx-5 gx-xxl-6">
|
||||
<Col lg={5} xl={4} className="d-none d-lg-block">
|
||||
<SocialProfileCard
|
||||
showAbout={true}
|
||||
avatar={profileImage}
|
||||
className="mb-5"
|
||||
/>
|
||||
<ProfileNavigation />
|
||||
<div className="mb-8 mt-6">
|
||||
<SocialMessages messages={messages} />
|
||||
</div>
|
||||
<div className="mb-8">
|
||||
<SocialPhotos photos={socialPhotos} />
|
||||
</div>
|
||||
<Events events={events} title="Events" />
|
||||
</Col>
|
||||
<Col lg={7} xl={8}>
|
||||
<FeedTextarea className="mb-5" />
|
||||
<SocialPosts posts={feedPosts} />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<NavbarBottom active="home" className="d-lg-none" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Feed;
|
||||
62
src/pages/apps/social/Settings.tsx
Normal file
62
src/pages/apps/social/Settings.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import Button from 'components/base/Button';
|
||||
import SocialProfileCard from 'components/cards/SocialProfileCard';
|
||||
import SettingsChangePassword from 'components/forms/SettingsChangePassword';
|
||||
import SettingsCompanyInfo from 'components/forms/SettingsCompanyInfo';
|
||||
import SettingsPersonalInfo from 'components/forms/SettingsPersonalInfo';
|
||||
import SettingsSocial from 'components/forms/SettingsSocial';
|
||||
import SocialSettingsSideBar from 'components/modules/social/SocialSettingsSideBar';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import profileImage from 'assets/img/team/20.webp';
|
||||
|
||||
const Settings = () => {
|
||||
return (
|
||||
<div className="mb-9">
|
||||
<Row className="g-6">
|
||||
<Col xs={12} xl={4}>
|
||||
<SocialProfileCard avatar={profileImage} className="mb-5" />
|
||||
<SocialSettingsSideBar />
|
||||
</Col>
|
||||
<Col xs={12} xl={8}>
|
||||
<div className="border-bottom mb-4">
|
||||
<SettingsPersonalInfo />
|
||||
<Row className="gx-3 mb-6 gy-6 gy-sm-3">
|
||||
<Col xs={12} sm={6}>
|
||||
<SettingsCompanyInfo />
|
||||
</Col>
|
||||
<Col xs={12} sm={6}>
|
||||
<SettingsChangePassword />
|
||||
</Col>
|
||||
</Row>
|
||||
<SettingsSocial />
|
||||
<div className="text-end mb-6">
|
||||
<Button variant="phoenix-secondary" className="me-2">
|
||||
Cancel Changes
|
||||
</Button>
|
||||
<Button variant="phoenix-primary">Save Information</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Row className="gy-5">
|
||||
<Col xs={12} md={6}>
|
||||
<h4 className="text-body-emphasis">Transfer Ownership</h4>
|
||||
<p className="text-body-tertiary">
|
||||
Transfer this account to another person or to a company
|
||||
repository.
|
||||
</p>
|
||||
<Button variant="phoenix-warning">Transfer</Button>
|
||||
</Col>
|
||||
<Col xs={12} md={6}>
|
||||
<h4 className="text-body-emphasis">Account Deletion</h4>
|
||||
<p className="text-body-tertiary">
|
||||
Transfer this account to another person or to a company
|
||||
repository.
|
||||
</p>
|
||||
<Button variant="phoenix-danger">Delete account</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Settings;
|
||||
43
src/pages/apps/social/SocialProfile.tsx
Normal file
43
src/pages/apps/social/SocialProfile.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import SocialCoverCard from 'components/cards/SocialCoverCard';
|
||||
import NavbarBottom from 'components/modules/social/NavbarBottom';
|
||||
import MutualNavigation from 'components/list-items/MutualNavigation';
|
||||
import SocialPhotos from 'components/image-gallery/SocialPhotos';
|
||||
import SocialPosts from 'components/modules/social/SocialPosts';
|
||||
import { profilePosts, socialPhotos } from 'data/social/postsData';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import ProfileNavigation from 'components/list-items/ProfileNavigation';
|
||||
import { useMainLayoutContext } from 'providers/MainLayoutProvider';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const SocialProfile = () => {
|
||||
const { setFooterClass, setContentClass } = useMainLayoutContext();
|
||||
|
||||
useEffect(() => {
|
||||
setFooterClass('d-none d-lg-block');
|
||||
setContentClass('widget-gap-large');
|
||||
return () => {
|
||||
setFooterClass('');
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-9">
|
||||
<SocialCoverCard />
|
||||
<Row className="gy-3 gx-5 gx-xxl-6">
|
||||
<Col xl={4} className="d-none d-xl-block">
|
||||
<ProfileNavigation className="mb-8" />
|
||||
<SocialPhotos className="mb-8" photos={socialPhotos} />
|
||||
<MutualNavigation />
|
||||
</Col>
|
||||
<Col xl={8}>
|
||||
<SocialPosts posts={profilePosts} />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<NavbarBottom active="profile" className="d-xl-none" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SocialProfile;
|
||||
57
src/pages/apps/travel-agency/flight/Booking.tsx
Normal file
57
src/pages/apps/travel-agency/flight/Booking.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Container, Row, Col } from 'react-bootstrap';
|
||||
import FlightBookingWizard from '../payment/FlightBookingWizard';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faClock } from '@fortawesome/free-solid-svg-icons';
|
||||
import FlightInfo from 'components/modules/travel-agency/flight/booking/FlightInfo';
|
||||
import FlightDetails from 'components/modules/travel-agency/flight/booking/FlightDetails';
|
||||
import CouponCard from 'components/cards/CuponCard';
|
||||
import PaymentSummary from 'components/modules/travel-agency/flight/booking/PaymentSummary';
|
||||
import TravelerDetails from 'components/modules/travel-agency/flight/booking/TravelerDetails';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { flightNavItems } from 'data/travel-agency/resizableNav';
|
||||
import FlightBottomBar from './BottomBar';
|
||||
|
||||
const FlightBooking = () => {
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={flightNavItems} />
|
||||
<Container fluid="small" className="pt-6 pb-6 pb-9">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} className="mb-3" />
|
||||
<h2 className="mb-5">Booking</h2>
|
||||
<Row className="g-3 align-items-sm-center justify-content-between mb-5">
|
||||
<Col sm>
|
||||
<FlightBookingWizard activeItem="Booking" />
|
||||
</Col>
|
||||
<Col sm className="text-sm-end">
|
||||
<div>
|
||||
<p className="mb-2 text-info">Book before time runs out</p>
|
||||
<h3 className="mb-0 text-info fw-bold d-flex gap-2 align-items-center justify-content-sm-end">
|
||||
<FontAwesomeIcon icon={faClock} className="fs-8" />
|
||||
<span>29</span>
|
||||
<span className="fs-9 fw-normal">min</span>
|
||||
<span>50</span>
|
||||
<span className="fs-9 fw-normal">sec</span>
|
||||
</h3>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<FlightInfo />
|
||||
<FlightDetails />
|
||||
<Row className="justify-content-between">
|
||||
<Col lg={8}>
|
||||
<TravelerDetails />
|
||||
<PaymentSummary />
|
||||
</Col>
|
||||
<Col lg={4}>
|
||||
<CouponCard />
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
<FlightBottomBar />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlightBooking;
|
||||
31
src/pages/apps/travel-agency/flight/BottomBar.tsx
Normal file
31
src/pages/apps/travel-agency/flight/BottomBar.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Button, Container } from 'react-bootstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faChevronRight } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
const FlightBottomBar = () => {
|
||||
return (
|
||||
<div className="flight-bottom-bar bg-secondary" data-bs-theme="light">
|
||||
<Container fluid="small" className="py-3">
|
||||
<div className="d-flex gap-4 gap-sm-6 align-items-center justify-content-end">
|
||||
<h6 className="text-white mb-0">
|
||||
<span className="me-2">Total</span>
|
||||
<span className="me-2">:</span>
|
||||
<span>BDT</span>
|
||||
<span className="fs-5 ms-2">4,609</span>
|
||||
</h6>
|
||||
<Button
|
||||
variant="primary"
|
||||
className="flex-1 text-nowrap"
|
||||
href="#!"
|
||||
style={{ maxWidth: '17rem' }}
|
||||
>
|
||||
Continue
|
||||
<FontAwesomeIcon icon={faChevronRight} className="fs-9 ms-2" />
|
||||
</Button>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlightBottomBar;
|
||||
52
src/pages/apps/travel-agency/flight/Homepage.tsx
Normal file
52
src/pages/apps/travel-agency/flight/Homepage.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import NavbarHome from 'components/navbars/travel-agency/NavbarHome';
|
||||
import { Container } from 'react-bootstrap';
|
||||
import bgIllustrations from 'assets/img/bg/44.png';
|
||||
import FlightSearch from 'components/modules/travel-agency/flight/homepage/FlightSearch';
|
||||
import FlightListing from 'components/modules/travel-agency/flight/homepage/FlightListing';
|
||||
import FlightFooter from 'components/modules/travel-agency/flight/homepage/FlightFooter';
|
||||
import FlightPromoModal from 'components/modals/FlightPromoModal';
|
||||
import { useState } from 'react';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { flightNavItems } from 'data/travel-agency/resizableNav';
|
||||
|
||||
const FlightHomepage = () => {
|
||||
const [showPromoModal, setShowPromoModal] = useState(true);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={flightNavItems} />
|
||||
<section className="container-small py-0">
|
||||
<NavbarHome currentPage="Flight" />
|
||||
</section>
|
||||
<section className="p-0">
|
||||
<Container fluid className="px-0">
|
||||
<div className="position-relative" style={{ height: '19rem' }}>
|
||||
<div
|
||||
className="bg-holder"
|
||||
style={{
|
||||
backgroundImage: `url(${bgIllustrations})`,
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Container>
|
||||
<Container
|
||||
fluid="small"
|
||||
className="mb-6"
|
||||
style={{ marginTop: '-12rem' }}
|
||||
>
|
||||
<FlightSearch />
|
||||
<FlightListing />
|
||||
</Container>
|
||||
<FlightFooter />
|
||||
</section>
|
||||
<FlightPromoModal
|
||||
show={showPromoModal}
|
||||
handleClose={() => setShowPromoModal(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlightHomepage;
|
||||
47
src/pages/apps/travel-agency/flight/Payment.tsx
Normal file
47
src/pages/apps/travel-agency/flight/Payment.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Card, Col, Container, Row } from 'react-bootstrap';
|
||||
import FlightBookingWizard from '../payment/FlightBookingWizard';
|
||||
import CountdownDisplay from '../payment/CountdownDisplay';
|
||||
import FlightPaymentInfo from './PaymentInfo';
|
||||
import PaymentMethodForm from 'components/forms/PaymentMethodForm';
|
||||
import FlightBottomBar from './BottomBar';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { flightNavItems } from 'data/travel-agency/resizableNav';
|
||||
|
||||
const FlightPayment = () => {
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={flightNavItems} />
|
||||
<Container fluid="small" className="pt-6 pb-9">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} className="mb-3" />
|
||||
<h2 className="mb-5">Payment</h2>
|
||||
<Row className="g-3 align-items-sm-center justify-content-between mb-5">
|
||||
<Col sm>
|
||||
<FlightBookingWizard activeItem="Payment" />
|
||||
</Col>
|
||||
<Col sm className="text-sm-end">
|
||||
<CountdownDisplay />
|
||||
</Col>
|
||||
</Row>
|
||||
<hr className="mt-5 mb-6" />
|
||||
<Row className="g-0 gap-6">
|
||||
<Col lg>
|
||||
<FlightPaymentInfo />
|
||||
</Col>
|
||||
<Col lg>
|
||||
<Card>
|
||||
<Card.Body>
|
||||
<PaymentMethodForm marginTop="short" />
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<hr className="mt-6 mb-9 d-none d-lg-block" />
|
||||
</Container>
|
||||
<FlightBottomBar />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlightPayment;
|
||||
191
src/pages/apps/travel-agency/flight/PaymentInfo.tsx
Normal file
191
src/pages/apps/travel-agency/flight/PaymentInfo.tsx
Normal file
@@ -0,0 +1,191 @@
|
||||
import { Button, Row, Col } from 'react-bootstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
faPlane,
|
||||
faEdit,
|
||||
faUser,
|
||||
faSuitcaseRolling,
|
||||
faCircle
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import qatarAirlineLogo from 'assets/img/brand/qatar-airline.png';
|
||||
|
||||
const FlightInfo = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="d-flex justify-content-between mb-4">
|
||||
<div>
|
||||
<FontAwesomeIcon icon={faPlane} className="text-primary me-2" />
|
||||
<h4 className="mb-0 d-inline-block text-body-highlight">
|
||||
Flight info
|
||||
</h4>
|
||||
</div>
|
||||
<Button variant="link" className="p-0">
|
||||
<FontAwesomeIcon icon={faEdit} className="me-2" />
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="mb-4 d-flex align-items-center">
|
||||
<img
|
||||
src={qatarAirlineLogo}
|
||||
alt=""
|
||||
style={{ height: '3.5rem' }}
|
||||
className="img-fluid rounded-3"
|
||||
/>
|
||||
<h5 className="text-nowrap fw-normal d-inline-block ms-2 mb-0">
|
||||
Qatar Airways
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<p className="text-body-emphasis">
|
||||
Travelling from <strong>Dhaka</strong> to <strong>Cox’s Bazar</strong>
|
||||
</p>
|
||||
|
||||
<div className="d-flex gap-2 flex-wrap">
|
||||
<p className="mb-0 text-body-emphasis text-nowrap">
|
||||
Tuesday, 29 January
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="text-body-tertiary fs-11 mx-2"
|
||||
transform="shrink-6"
|
||||
/>
|
||||
5:00 pm
|
||||
</p>
|
||||
<p className="mb-0 text-body-emphasis text-nowrap">
|
||||
<span className="text-body-tertiary me-2">-</span>
|
||||
Tuesday, 29 January
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="text-body-tertiary fs-11 mx-2"
|
||||
transform="shrink-6"
|
||||
/>
|
||||
5:30 pm
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const PersonalInfo = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="d-flex justify-content-between mb-4">
|
||||
<div>
|
||||
<FontAwesomeIcon icon={faUser} className="text-primary me-2" />
|
||||
<h4 className="mb-0 d-inline-block text-body-highlight">
|
||||
Personal info
|
||||
</h4>
|
||||
</div>
|
||||
<Button variant="link" className="p-0">
|
||||
<FontAwesomeIcon icon={faEdit} className="me-2" />
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="bg-body-highlight rounded-2 p-4">
|
||||
<Row className="g-0 gy-5 flex-column flex-sm-row">
|
||||
<Col className="pe-4">
|
||||
<h5 className="mb-3">Passenger 1</h5>
|
||||
<p className="mb-2">John James Johansen</p>
|
||||
<p className="mb-0">
|
||||
Adult
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="text-body-tertiary fs-11 mx-2"
|
||||
transform="shrink-5"
|
||||
/>
|
||||
Male
|
||||
</p>
|
||||
</Col>
|
||||
<Col className="border-start-sm border-top-sm-0 border-top border-translucent ps-sm-4 pt-4 pt-sm-0">
|
||||
<h5 className="mb-3">Passenger 2</h5>
|
||||
<p className="mb-2">John James Johansen</p>
|
||||
<p className="mb-0">
|
||||
Adult
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="text-body-tertiary fs-11 mx-2"
|
||||
transform="shrink-5"
|
||||
/>
|
||||
Male
|
||||
</p>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const BaggageInfo = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="d-flex justify-content-between mb-4">
|
||||
<div>
|
||||
<FontAwesomeIcon
|
||||
icon={faSuitcaseRolling}
|
||||
className="text-primary me-2"
|
||||
/>
|
||||
<h4 className="mb-0 d-inline-block text-body-highlight">
|
||||
Included baggage
|
||||
</h4>
|
||||
</div>
|
||||
<Button variant="link" className="p-0">
|
||||
<FontAwesomeIcon icon={faEdit} className="me-2" />
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="d-flex gap-3 mb-4">
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="text-body-quaternary fs-11 mx-2"
|
||||
transform="down-8"
|
||||
/>
|
||||
<div>
|
||||
<h5 className="mb-2">1 personal item</h5>
|
||||
<p className="mb-0 text-body-tertiary">
|
||||
Must go under the seat in front of you
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="d-flex gap-3 mb-4">
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="text-body-quaternary fs-11 mx-2"
|
||||
transform="down-8"
|
||||
/>
|
||||
<div>
|
||||
<h5 className="mb-2">1 carry-on bag</h5>
|
||||
<p className="mb-0 text-body-tertiary">Max weight 8 kg</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="d-flex gap-3">
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="text-body-quaternary fs-11 mx-2"
|
||||
transform="down-8"
|
||||
/>
|
||||
<div>
|
||||
<h5 className="mb-2">1 checked bag</h5>
|
||||
<p className="mb-0 text-body-tertiary">Max weight 25 kg</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const FlightPaymentInfo = () => {
|
||||
return (
|
||||
<div>
|
||||
<FlightInfo />
|
||||
<hr className="my-5" />
|
||||
<PersonalInfo />
|
||||
<hr className="my-5" />
|
||||
<BaggageInfo />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlightPaymentInfo;
|
||||
124
src/pages/apps/travel-agency/hotel/admin/AddProperty.tsx
Normal file
124
src/pages/apps/travel-agency/hotel/admin/AddProperty.tsx
Normal file
@@ -0,0 +1,124 @@
|
||||
import WizardForm from 'components/wizard/WizardForm';
|
||||
import useWizardForm from 'hooks/useWizardForm';
|
||||
import WizardFormProvider from 'providers/WizardFormProvider';
|
||||
import { Col, Row, Tab } from 'react-bootstrap';
|
||||
import WizardFormFooter from 'components/wizard/WizardFormFooter';
|
||||
import classNames from 'classnames';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
// import BasicInformationForm from 'components/modules/travel-agency/dashboard/hotel/add-proterty/BasicInformationForm';
|
||||
import LocationForm from 'components/modules/travel-agency/hotel/add-proterty/LocationForm';
|
||||
import GeneralAmenitiesForm from 'components/modules/travel-agency/hotel/add-proterty/GeneralAmenitiesForm';
|
||||
import AddPhotos from 'components/modules/travel-agency/hotel/add-proterty/AddPhotos';
|
||||
import FinanceForm from 'components/modules/travel-agency/hotel/add-proterty/FinanceForm';
|
||||
import Preview from 'components/modules/travel-agency/hotel/add-proterty/Preview';
|
||||
import { addPropertyWizardNav } from 'data/wizard/wizard';
|
||||
import WizardSideNav from 'components/wizard/WizardSideNav';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { urlToFile } from 'helpers/utils';
|
||||
import {
|
||||
addPropertyDefaultFormData,
|
||||
pictures
|
||||
} from 'data/travel-agency/addProperty';
|
||||
import PoliciesForm from 'components/modules/travel-agency/hotel/add-proterty/PoliciesForm';
|
||||
import BasicInformationForm from 'components/modules/travel-agency/hotel/add-proterty/BasicInformationForm';
|
||||
|
||||
const AddProperty = () => {
|
||||
const [images, setImages] = useState<File[]>([]);
|
||||
const [tabEventKey, setTabEventKey] = useState(1);
|
||||
const form = useWizardForm({
|
||||
totalStep: 7
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const loadImages = async () => {
|
||||
const imageFiles = await Promise.all(
|
||||
pictures.map(async picUrl => {
|
||||
return await urlToFile(picUrl);
|
||||
})
|
||||
);
|
||||
setImages(imageFiles);
|
||||
};
|
||||
|
||||
loadImages();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
form.setFormData({ ...addPropertyDefaultFormData, photos: images });
|
||||
}, [images]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-9">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} />
|
||||
<h2 className="fs-5 mb-4 mb-xl-5">Add New Property </h2>
|
||||
<WizardFormProvider {...form}>
|
||||
<Row className="gx-0 gx-xl-5 theme-wizard">
|
||||
<Col xl={{ order: 1, span: 4 }}>
|
||||
<div className="scrollbar mb-4">
|
||||
<WizardSideNav
|
||||
navItems={addPropertyWizardNav}
|
||||
setTabEventKey={setTabEventKey}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
<Col xl={8} className="flex-1">
|
||||
<Row>
|
||||
<Col xxl={8}>
|
||||
<Tab.Content>
|
||||
<Tab.Pane eventKey={1}>
|
||||
<WizardForm step={1}>
|
||||
<BasicInformationForm />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
<Tab.Pane eventKey={2}>
|
||||
<WizardForm step={2}>
|
||||
<LocationForm tabEventKey={tabEventKey} />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
<Tab.Pane eventKey={3}>
|
||||
<WizardForm step={3}>
|
||||
<GeneralAmenitiesForm />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
<Tab.Pane eventKey={4}>
|
||||
<WizardForm step={4}>
|
||||
<AddPhotos
|
||||
title="Add property picture"
|
||||
images={images}
|
||||
/>
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
<Tab.Pane eventKey={5}>
|
||||
<WizardForm step={5}>
|
||||
<FinanceForm />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
<Tab.Pane eventKey={6}>
|
||||
<WizardForm step={6}>
|
||||
<PoliciesForm />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
<Tab.Pane eventKey={7}>
|
||||
<WizardForm step={7}>
|
||||
<Preview />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
</Tab.Content>
|
||||
<div className="mt-6">
|
||||
<WizardFormFooter
|
||||
hidePrevBtn
|
||||
className={classNames({ 'd-none': !form.getCanNextPage })}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</WizardFormProvider>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddProperty;
|
||||
93
src/pages/apps/travel-agency/hotel/admin/AddRoom.tsx
Normal file
93
src/pages/apps/travel-agency/hotel/admin/AddRoom.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Row, Col, Tab } from 'react-bootstrap';
|
||||
import useWizardForm from 'hooks/useWizardForm';
|
||||
import WizardForm from 'components/wizard/WizardForm';
|
||||
import WizardFormProvider from 'providers/WizardFormProvider';
|
||||
import RoomDetailsForm from 'components/modules/travel-agency/hotel/add-room/RoomDetailsForm';
|
||||
import { addRoomWizardNav } from 'data/wizard/wizard';
|
||||
import RoomWizardFooter from 'components/modules/travel-agency/hotel/add-room/RoomWizardFooter';
|
||||
import Pricing from 'components/modules/travel-agency/hotel/add-room/Pricing';
|
||||
import Amenities from 'components/modules/travel-agency/hotel/add-room/Amenities';
|
||||
import AddPhotos from 'components/modules/travel-agency/hotel/add-proterty/AddPhotos';
|
||||
import Preview from 'components/modules/travel-agency/hotel/add-room/Preview';
|
||||
import WizardSideNav from 'components/wizard/WizardSideNav';
|
||||
import { urlToFile } from 'helpers/utils';
|
||||
import { pictures } from 'data/travel-agency/addProperty';
|
||||
import { addRoomDefaultFormData } from 'data/travel-agency/addRoom';
|
||||
|
||||
const AddRoom = () => {
|
||||
const [images, setImages] = useState<File[]>([]);
|
||||
|
||||
const form = useWizardForm({
|
||||
totalStep: 5
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const loadImages = async () => {
|
||||
const imageFiles = await Promise.all(
|
||||
pictures.map(async picUrl => {
|
||||
return await urlToFile(picUrl);
|
||||
})
|
||||
);
|
||||
setImages(imageFiles);
|
||||
};
|
||||
|
||||
loadImages();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
form.setFormData({ ...addRoomDefaultFormData, pictures: images });
|
||||
}, [images]);
|
||||
|
||||
return (
|
||||
<div className="mb-9">
|
||||
<PageBreadcrumb className="mb-3" items={defaultBreadcrumbItems} />
|
||||
<h2 className="fs-5 mb-4 mb-xl-5">Add New Room</h2>
|
||||
<WizardFormProvider {...form}>
|
||||
<Row className="gx-0 gx-xl-5 theme-wizard">
|
||||
<Col xl={{ order: 1, span: 4 }}>
|
||||
<WizardSideNav navItems={addRoomWizardNav} />
|
||||
</Col>
|
||||
<Col xl={8} className="flex-1">
|
||||
<Row className="mt-4 mt-xl-0">
|
||||
<Col xxl={8}>
|
||||
<Tab.Content>
|
||||
<Tab.Pane eventKey={1}>
|
||||
<WizardForm step={1}>
|
||||
<RoomDetailsForm />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
<Tab.Pane eventKey={2}>
|
||||
<WizardForm step={2}>
|
||||
<Pricing />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
<Tab.Pane eventKey={3}>
|
||||
<WizardForm step={3}>
|
||||
<Amenities />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
<Tab.Pane eventKey={4}>
|
||||
<WizardForm step={4}>
|
||||
<AddPhotos title="Add room picture" images={images} />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
<Tab.Pane eventKey={5}>
|
||||
<WizardForm step={5}>
|
||||
<Preview />
|
||||
</WizardForm>
|
||||
</Tab.Pane>
|
||||
</Tab.Content>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
<RoomWizardFooter />
|
||||
</WizardFormProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddRoom;
|
||||
15
src/pages/apps/travel-agency/hotel/admin/RoomListing.tsx
Normal file
15
src/pages/apps/travel-agency/hotel/admin/RoomListing.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import RoomListingTable from 'components/tables/RoomListingTable';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
|
||||
const RoomListing = () => {
|
||||
return (
|
||||
<div className="mb-9">
|
||||
<PageBreadcrumb className="mb-3" items={defaultBreadcrumbItems} />
|
||||
<h2>Room Listing</h2>
|
||||
<RoomListingTable />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RoomListing;
|
||||
144
src/pages/apps/travel-agency/hotel/admin/SearchRoom.tsx
Normal file
144
src/pages/apps/travel-agency/hotel/admin/SearchRoom.tsx
Normal file
@@ -0,0 +1,144 @@
|
||||
import {
|
||||
faCalendarAlt,
|
||||
faChevronRight,
|
||||
faFilter,
|
||||
faRotate,
|
||||
faSearch
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import DatePicker from 'components/base/DatePicker';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import RoomCard from 'components/modules/travel-agency/hotel/search-room/RoomCard';
|
||||
import RoomFilterOffcanvas from 'components/modules/travel-agency/hotel/search-room/RoomFilterOffcanvas';
|
||||
import RoomFilterOffcanvasContent from 'components/modules/travel-agency/hotel/search-room/RoomFilterOffcanvasContent';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { useState } from 'react';
|
||||
import { Row, Col, Form, FloatingLabel } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { roomsSearchData } from 'data/travel-agency/customer/hotel';
|
||||
|
||||
const SearchRoom = () => {
|
||||
const [openOffcanvas, setOpenOffcanvas] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} className="mb-3" />
|
||||
<div className="mb-9">
|
||||
<Row className="align-items-end mb-5 gy-3">
|
||||
<Col style={{ maxWidth: 290 }}>
|
||||
<h2>Rooms</h2>
|
||||
</Col>
|
||||
<Col xl>
|
||||
<Row className="gx-2 gx-xl-3 gy-3">
|
||||
<Col
|
||||
xs={{ order: 1 }}
|
||||
sm={{ span: 'auto', order: 0 }}
|
||||
className="me-sm-2 d-xl-none"
|
||||
>
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
size="lg"
|
||||
className="text-body-tertiary w-100"
|
||||
onClick={() => setOpenOffcanvas(true)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faFilter} className="me-2" />
|
||||
Filter
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs sm={5} xxl={3}>
|
||||
<DatePicker
|
||||
render={(_, ref) => {
|
||||
return (
|
||||
<FloatingLabel
|
||||
label="Select Time Range"
|
||||
className="w-auto"
|
||||
>
|
||||
<Form.Control
|
||||
type="text"
|
||||
placeholder="start date"
|
||||
ref={ref}
|
||||
id="startDatepicker"
|
||||
className="ps-3"
|
||||
/>
|
||||
|
||||
<FontAwesomeIcon
|
||||
icon={faCalendarAlt}
|
||||
className="position-absolute top-0 end-0 mt-3 me-3"
|
||||
/>
|
||||
</FloatingLabel>
|
||||
);
|
||||
}}
|
||||
hideIcon={true}
|
||||
options={{
|
||||
mode: 'range',
|
||||
minDate: 'today',
|
||||
dateFormat: 'Y-m-d'
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs sm="auto" className="flex-grow-0">
|
||||
<Button
|
||||
variant="phoenix-primary"
|
||||
size="lg"
|
||||
className="px-xxl-6 text-nowrap"
|
||||
>
|
||||
<span className="d-none d-xl-inline-block">Update</span>
|
||||
<FontAwesomeIcon icon={faSearch} className="fs-9 ms-xl-2" />
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs sm="auto" className="ms-auto flex-grow-0">
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
size="lg"
|
||||
className="ms-auto text-nowrap"
|
||||
>
|
||||
<span className="d-none d-xl-inline-block">Refresh</span>
|
||||
<FontAwesomeIcon icon={faRotate} className="fs-9 ms-xl-2" />
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
{/* header section end */}
|
||||
|
||||
<Row className="gx-6">
|
||||
{/* offcanvas start */}
|
||||
<Col xl="auto" className="d-none d-xl-block">
|
||||
<div className="phoenix-room-filter-offcanvas bg-body scrollbar">
|
||||
<RoomFilterOffcanvasContent />
|
||||
</div>
|
||||
</Col>
|
||||
{/* offcanvas end */}
|
||||
<Col className="w-xl-25">
|
||||
{roomsSearchData.map((item, index) => (
|
||||
<RoomCard
|
||||
key={index}
|
||||
data={item}
|
||||
isLastItem={roomsSearchData.length - 1 === index}
|
||||
/>
|
||||
))}
|
||||
<div className="border p-3 rounded-3 mt-5 d-flex flex-end-center gap-3 gap-sm-6 flex-wrap">
|
||||
<h2 className="text-body mb-0">
|
||||
<span className="fs-9 text-body-tertiary fw-bold me-2">
|
||||
Total :
|
||||
</span>
|
||||
04
|
||||
</h2>
|
||||
<Link to="#!">
|
||||
<Button variant="primary" className="px-sm-7">
|
||||
Confirm Booking
|
||||
<FontAwesomeIcon icon={faChevronRight} className="ms-2" />
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<RoomFilterOffcanvas open={openOffcanvas} setOpen={setOpenOffcanvas} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchRoom;
|
||||
251
src/pages/apps/travel-agency/hotel/customer/HotelCheckout.tsx
Normal file
251
src/pages/apps/travel-agency/hotel/customer/HotelCheckout.tsx
Normal file
@@ -0,0 +1,251 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import TravelFooter from 'components/footers/TravelFooter';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Container, Row, Col, Form } from 'react-bootstrap';
|
||||
import HotelDetailsSummaryCard from 'components/cards/HotelDetailsSummaryCard';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faChevronRight, faCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
import Button from 'components/base/Button';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { hotelNavItems } from 'data/travel-agency/resizableNav';
|
||||
|
||||
const HotelCheckout = () => {
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={hotelNavItems} />
|
||||
<section className="pt-6 pb-9">
|
||||
<Container fluid="medium">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} className="mb-3" />
|
||||
<h2 className="mb-5">Check out</h2>
|
||||
<Row className="justify-content-between">
|
||||
<Col lg={7} xl={6}>
|
||||
<Form id="checkoutForm1" onSubmit={e => e.preventDefault()}>
|
||||
<hr className="mt-0 mb-7" />
|
||||
<h3 className="fw-bold mb-5">Enter your details</h3>
|
||||
<h5 className="mb-3">Are you travelling for work?</h5>
|
||||
<Form.Check
|
||||
id="tripTypeRadio"
|
||||
className="form-check-inline me-4"
|
||||
>
|
||||
<Form.Check.Input
|
||||
type="radio"
|
||||
name="tripTypeRadio"
|
||||
value="no"
|
||||
defaultChecked
|
||||
/>
|
||||
<Form.Check.Label htmlFor="tripTypeRadio">
|
||||
No
|
||||
</Form.Check.Label>
|
||||
</Form.Check>
|
||||
<Form.Check id="tripTypeRadio" className="form-check-inline">
|
||||
<Form.Check.Input
|
||||
type="radio"
|
||||
name="tripTypeRadio"
|
||||
value="yes"
|
||||
/>
|
||||
<Form.Check.Label htmlFor="tripTypeRadio">
|
||||
Yes
|
||||
</Form.Check.Label>
|
||||
</Form.Check>
|
||||
<Row className="g-3 mb-5 mt-1">
|
||||
<Col sm={6}>
|
||||
<label
|
||||
htmlFor="first-name"
|
||||
className="fw-bold text-body-highlight mb-1"
|
||||
>
|
||||
First name
|
||||
</label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
id="first-name"
|
||||
placeholder="First name"
|
||||
/>
|
||||
</Col>
|
||||
<Col sm={6}>
|
||||
<label
|
||||
htmlFor="last-name"
|
||||
className="fw-bold text-body-highlight mb-1"
|
||||
>
|
||||
Last name
|
||||
</label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
id="last-name"
|
||||
placeholder="Last name"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="g-3">
|
||||
<Col sm={6}>
|
||||
<label
|
||||
htmlFor="email-address"
|
||||
className="fw-bold text-body-highlight mb-1"
|
||||
>
|
||||
Email address
|
||||
</label>
|
||||
<Form.Control
|
||||
type="email"
|
||||
id="email-address"
|
||||
placeholder="Email address"
|
||||
/>
|
||||
</Col>
|
||||
<Col sm={6}>
|
||||
<label
|
||||
htmlFor="confirm-email-address"
|
||||
className="fw-bold text-body-highlight mb-1"
|
||||
>
|
||||
Confirm email address
|
||||
</label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
id="confirm-email-address"
|
||||
placeholder="Confirm email address "
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<h5 className="mb-3 mt-7">Who are you booking for?</h5>
|
||||
<Form.Check
|
||||
id="bookingPersonRadio"
|
||||
className="form-check-inline me-4"
|
||||
>
|
||||
<Form.Check.Input
|
||||
type="radio"
|
||||
name="bookingPersonRadio"
|
||||
id="me"
|
||||
value="no"
|
||||
defaultChecked
|
||||
/>
|
||||
<Form.Check.Label htmlFor="me">
|
||||
I am the main guest
|
||||
</Form.Check.Label>
|
||||
</Form.Check>
|
||||
<Form.Check
|
||||
id="bookingPersonRadio"
|
||||
className="form-check-inline"
|
||||
>
|
||||
<Form.Check.Input
|
||||
type="radio"
|
||||
name="bookingPersonRadio"
|
||||
value="yes"
|
||||
id="else"
|
||||
/>
|
||||
<Form.Check.Label htmlFor="else">
|
||||
I am booking for somebody else
|
||||
</Form.Check.Label>
|
||||
</Form.Check>
|
||||
<h5 className="mb-3 mt-6">Add to your stay</h5>
|
||||
<Form.Check className="mb-4">
|
||||
<Form.Check.Input type="checkbox" id="airportShuttle" />
|
||||
<Form.Check.Label
|
||||
htmlFor="airportShuttle"
|
||||
className="fw-normal fs-8 text-body"
|
||||
>
|
||||
I am interested in requesting an airport shuttle
|
||||
<span className="d-block fs-9 text-body-tertiary">
|
||||
We'll tell your accommodation what you're interested in so
|
||||
they can provide details and costs.
|
||||
</span>
|
||||
</Form.Check.Label>
|
||||
</Form.Check>
|
||||
<Form.Check>
|
||||
<Form.Check.Input type="checkbox" id="rentingCar" />
|
||||
<Form.Check.Label
|
||||
htmlFor="rentingCar"
|
||||
className="fw-normal fs-8 text-body"
|
||||
>
|
||||
I'm interested in renting a car
|
||||
<span className="d-block fs-9 text-body-tertiary">
|
||||
Make the most of your trip and check the car rental
|
||||
options in your booking confirmation.
|
||||
</span>
|
||||
</Form.Check.Label>
|
||||
</Form.Check>
|
||||
<h5 className="mb-3 mt-6">Your arrival time</h5>
|
||||
<Row className="gx-2">
|
||||
<Col xs={6} sm={3}>
|
||||
<Form.Select role="select-box">
|
||||
<option value="1">12:00</option>
|
||||
<option value="2">03:00</option>
|
||||
<option value="3">06:00</option>
|
||||
<option value="4">09:00</option>
|
||||
</Form.Select>
|
||||
</Col>
|
||||
<Col xs={6} sm={3}>
|
||||
<Form.Select role="select-box">
|
||||
<option value="am">AM</option>
|
||||
<option value="pm">PM</option>
|
||||
</Form.Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<h5 className="mb-3 mt-7">Review house rules</h5>
|
||||
<p>
|
||||
Your host would like you to agree to the following house
|
||||
rules:
|
||||
</p>
|
||||
<p className="mb-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="text-body-quaternary fs-10 me-2"
|
||||
transform="up-2"
|
||||
/>
|
||||
No smoking
|
||||
</p>
|
||||
<p>
|
||||
<FontAwesomeIcon
|
||||
icon={faCircle}
|
||||
className="text-body-quaternary fs-10 me-2"
|
||||
transform="up-2"
|
||||
/>
|
||||
Pets are not allowed
|
||||
</p>
|
||||
<p className="text-info mb-7">
|
||||
By continuing to the next step, you are agreeing to these
|
||||
house rules.
|
||||
</p>
|
||||
<h5 className="mb-3">Special requests</h5>
|
||||
<p className="fs-9 text-body-tertiary mb-4">
|
||||
Special requests cannot be guaranteed, but the property will
|
||||
do its best to meet your needs. You can always make a special
|
||||
request after your booking is complete!
|
||||
</p>
|
||||
<Form.Control
|
||||
as="textarea"
|
||||
name="requestText"
|
||||
rows={5}
|
||||
id="requestText"
|
||||
placeholder="Type your request"
|
||||
/>
|
||||
<hr className="mt-7 mb-5" />
|
||||
<Link to="/apps/travel-agency/hotel/customer/payment">
|
||||
<Button
|
||||
variant="primary"
|
||||
endIcon={
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronRight}
|
||||
className="ms-2"
|
||||
transform="shrink-3"
|
||||
/>
|
||||
}
|
||||
>
|
||||
Final details
|
||||
</Button>
|
||||
</Link>
|
||||
</Form>
|
||||
</Col>
|
||||
<Col lg={5} xl={4}>
|
||||
<HotelDetailsSummaryCard
|
||||
showHotelInfo={true}
|
||||
className="mt-5 mt-lg-0"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</section>
|
||||
<TravelFooter />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HotelCheckout;
|
||||
64
src/pages/apps/travel-agency/hotel/customer/HotelCompare.tsx
Normal file
64
src/pages/apps/travel-agency/hotel/customer/HotelCompare.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import EcomTopRegionsMap from 'components/leaflet-maps/EcomTopRegionsMap';
|
||||
import { mapMarkerPoints } from 'data/mapMarkerPoints';
|
||||
import CollapsibleContainer from 'components/common/CollapsibleContainer';
|
||||
import CompareHotelDetails from 'components/modules/travel-agency/hotel/hotel-compare/CompareHotelDetails';
|
||||
import {
|
||||
hotelInfo,
|
||||
popularAmenitiesFields,
|
||||
reviewFields
|
||||
} from 'data/travel-agency/customer/hotelCompare';
|
||||
import CompareRoomDetails from 'components/modules/travel-agency/hotel/hotel-compare/CompareRoomDetails';
|
||||
import HotelActions from 'components/modules/travel-agency/hotel/HotelActions';
|
||||
import { Container } from 'react-bootstrap';
|
||||
import TravelFooter from 'components/footers/TravelFooter';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { hotelNavItems } from 'data/travel-agency/resizableNav';
|
||||
|
||||
const HotelCompare = () => {
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={hotelNavItems} />
|
||||
<section className="pt-6 pb-9">
|
||||
<Container fluid="medium">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} className="mb-3" />
|
||||
<h2 className="mb-4">Hotel Compare</h2>
|
||||
<HotelActions background={false} />
|
||||
<div
|
||||
className="w-100 border rounded-3 overflow-hidden my-5"
|
||||
style={{
|
||||
height: 220
|
||||
}}
|
||||
>
|
||||
<EcomTopRegionsMap data={mapMarkerPoints} />
|
||||
</div>
|
||||
<div className="position-relative scrollbar">
|
||||
<CollapsibleContainer
|
||||
collapseTitle="Hotel Details"
|
||||
id="hotelDetailsCollapse"
|
||||
>
|
||||
<CompareHotelDetails
|
||||
hotelInfo={hotelInfo}
|
||||
reviewFields={reviewFields}
|
||||
/>
|
||||
</CollapsibleContainer>
|
||||
<CollapsibleContainer
|
||||
collapseTitle="Room Details"
|
||||
id="roomDetailsCollapse"
|
||||
className="mt-8"
|
||||
>
|
||||
<CompareRoomDetails
|
||||
hotelInfo={hotelInfo}
|
||||
reviewFields={popularAmenitiesFields}
|
||||
/>
|
||||
</CollapsibleContainer>
|
||||
</div>
|
||||
</Container>
|
||||
</section>
|
||||
<TravelFooter />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HotelCompare;
|
||||
109
src/pages/apps/travel-agency/hotel/customer/HotelDetails.tsx
Normal file
109
src/pages/apps/travel-agency/hotel/customer/HotelDetails.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Container, Row, Col } from 'react-bootstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Badge from 'components/base/Badge';
|
||||
import Button from 'components/base/Button';
|
||||
import {
|
||||
faEnvelope,
|
||||
faMap,
|
||||
faMapMarkerAlt,
|
||||
faPhone
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import HotelDetailsSummaryCard from 'components/cards/HotelDetailsSummaryCard';
|
||||
import { hotelImages } from 'data/travel-agency/customer/hotelDetails';
|
||||
import HotelDetailsTab from 'components/modules/travel-agency/hotel/hotel-details/HotelDetailsTab';
|
||||
import HotelDetailsGallery from 'components/image-gallery/HotelDetailsGallery';
|
||||
import { numberFormat } from 'helpers/utils';
|
||||
import TravelFooter from 'components/footers/TravelFooter';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { hotelNavItems } from 'data/travel-agency/resizableNav';
|
||||
|
||||
const HotelDetails = () => {
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={hotelNavItems} />
|
||||
<section className="pt-4 pb-9">
|
||||
<Container fluid="medium">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} className="mb-3" />
|
||||
<h2 className="mb-4">Hotel Details</h2>
|
||||
<Row className="g-4 flex-between-end mb-5">
|
||||
<Col md={8} lg={9}>
|
||||
<h1 className="mb-2 fw-semibold">
|
||||
Radisson Blu Water Garden Hotel, Dhaka
|
||||
</h1>
|
||||
<div className="mb-1">
|
||||
<Link className="text-body-tertiary" to="#!">
|
||||
<FontAwesomeIcon
|
||||
icon={faMapMarkerAlt}
|
||||
className="me-2 text-body"
|
||||
/>
|
||||
Airport Rd, Dhaka Cantonment, Dhaka, 1206, Bangladesh
|
||||
</Link>
|
||||
</div>
|
||||
<div className="mb-1">
|
||||
<Link className="text-body-tertiary" to="tel:+88029834555">
|
||||
<FontAwesomeIcon icon={faPhone} className="me-2 text-body" />
|
||||
+880 29834555
|
||||
</Link>
|
||||
</div>
|
||||
<div className="mb-1">
|
||||
<Link
|
||||
className="text-body-tertiary"
|
||||
to="mailto:sales.dhaka@radisson.com"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faEnvelope}
|
||||
className="me-2 text-body"
|
||||
transform="down-1"
|
||||
/>
|
||||
sales.dhaka@radisson.com
|
||||
</Link>
|
||||
</div>
|
||||
</Col>
|
||||
<Col md={4} lg={3}>
|
||||
<div className="d-flex flex-md-column align-items-center align-items-md-end gap-3">
|
||||
<h5 className="mb-0 text-nowrap">
|
||||
<span className="text-body-tertiary me-2 fw-normal">
|
||||
Rated
|
||||
</span>
|
||||
<span className="text-primary me-2">Good</span>
|
||||
<Badge bg="primary">
|
||||
{numberFormat(4.3, 'standard', {
|
||||
minimumFractionDigits: 1,
|
||||
maximumFractionDigits: 1
|
||||
})}
|
||||
</Badge>
|
||||
</h5>
|
||||
<Button
|
||||
variant="phoenix-primary"
|
||||
className="px-5 px-lg-8 w-100 w-md-auto"
|
||||
startIcon={<FontAwesomeIcon icon={faMap} className="me-2" />}
|
||||
>
|
||||
Show in map
|
||||
</Button>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="g-3">
|
||||
<Col xl={8}>
|
||||
<HotelDetailsGallery images={hotelImages} />
|
||||
<HotelDetailsTab />
|
||||
</Col>
|
||||
<Col xl={4}>
|
||||
<HotelDetailsSummaryCard
|
||||
showHotelInfo={false}
|
||||
className="mt-3 mt-xl-0"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</section>
|
||||
<TravelFooter />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HotelDetails;
|
||||
27
src/pages/apps/travel-agency/hotel/customer/HotelGallery.tsx
Normal file
27
src/pages/apps/travel-agency/hotel/customer/HotelGallery.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import HotelGalleryImages from 'components/modules/travel-agency/hotel/HotelGalleryImages';
|
||||
import { galleryItems } from 'data/travel-agency/customer/gallery';
|
||||
import { Container } from 'react-bootstrap';
|
||||
import TravelFooter from 'components/footers/TravelFooter';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { hotelNavItems } from 'data/travel-agency/resizableNav';
|
||||
|
||||
const HotelGallery = () => {
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={hotelNavItems} />
|
||||
<section className="pt-6 pb-9">
|
||||
<Container fluid="medium">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} className="mb-3" />
|
||||
<h2 className="mb-5">Gallery</h2>
|
||||
<HotelGalleryImages galleryItems={galleryItems} />
|
||||
</Container>
|
||||
</section>
|
||||
<TravelFooter />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HotelGallery;
|
||||
123
src/pages/apps/travel-agency/hotel/customer/HotelPayment.tsx
Normal file
123
src/pages/apps/travel-agency/hotel/customer/HotelPayment.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Container, Row, Col, Form } from 'react-bootstrap';
|
||||
import HotelDetailsSummaryCard from 'components/cards/HotelDetailsSummaryCard';
|
||||
import PaymentMethodForm from 'components/forms/PaymentMethodForm';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faChevronLeft } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import Button from 'components/base/Button';
|
||||
import { Link } from 'react-router-dom';
|
||||
import TravelFooter from 'components/footers/TravelFooter';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { hotelNavItems } from 'data/travel-agency/resizableNav';
|
||||
|
||||
const HotelPayment = () => {
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={hotelNavItems} />
|
||||
<section className="pt-6 pb-9">
|
||||
<Container fluid="medium">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} className="mb-3" />
|
||||
<h2 className="mb-5">Payment</h2>
|
||||
<Row className="justify-content-between">
|
||||
<Col lg={7} xl={6}>
|
||||
<Form onSubmit={e => e.preventDefault()}>
|
||||
<Link to="/apps/travel-agency/hotel/customer/checkout">
|
||||
<Button
|
||||
variant="phoenix-primary"
|
||||
startIcon={
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronLeft}
|
||||
className="me-2"
|
||||
transform="shrink-3"
|
||||
/>
|
||||
}
|
||||
>
|
||||
Go back
|
||||
</Button>
|
||||
</Link>
|
||||
<hr className="mt-5 mb-7" />
|
||||
<h3 className="mb-5">Enter your address</h3>
|
||||
<Row className="g-3 mb-5">
|
||||
<Col sm={3}>
|
||||
<label
|
||||
htmlFor="country"
|
||||
className="fw-bold text-body-highlight mb-1"
|
||||
>
|
||||
Country
|
||||
</label>
|
||||
<Form.Select id="country">
|
||||
<option value="1">India</option>
|
||||
<option value="2">USA</option>
|
||||
<option value="3">UAE</option>
|
||||
</Form.Select>
|
||||
</Col>
|
||||
<Col sm={5} lg={4}>
|
||||
<label
|
||||
htmlFor="phone-number"
|
||||
className="fw-bold text-body-highlight mb-1"
|
||||
>
|
||||
Phone number
|
||||
</label>
|
||||
<Form.Control
|
||||
type="number"
|
||||
id="phone-number"
|
||||
placeholder="Enter phone number"
|
||||
className="input-spin-none"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="g-3">
|
||||
<Col sm={8} lg={7}>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="fw-bold text-body-highlight mb-1"
|
||||
>
|
||||
Email address
|
||||
</label>
|
||||
<Form.Control
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="Enter email address"
|
||||
id="email"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<PaymentMethodForm />
|
||||
<hr className="mt-6 mb-5" />
|
||||
<Link to="/apps/travel-agency/hotel/customer/checkout">
|
||||
<Button
|
||||
variant="phoenix-primary"
|
||||
className="me-3"
|
||||
startIcon={
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronLeft}
|
||||
className="me-2"
|
||||
transform="shrink-3"
|
||||
/>
|
||||
}
|
||||
>
|
||||
Go back
|
||||
</Button>
|
||||
</Link>
|
||||
<Button variant="primary" className="px-sm-15">
|
||||
Confirm booking
|
||||
</Button>
|
||||
</Form>
|
||||
</Col>
|
||||
<Col lg={5} xl={4}>
|
||||
<HotelDetailsSummaryCard
|
||||
showHotelInfo={true}
|
||||
className="mt-5 mt-lg-0"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</section>
|
||||
<TravelFooter />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HotelPayment;
|
||||
@@ -0,0 +1,65 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Col, Form, Row } from 'react-bootstrap';
|
||||
import Button from 'components/base/Button';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faFilter, faMap } from '@fortawesome/free-solid-svg-icons';
|
||||
import HotelCard from 'components/cards/HotelCard';
|
||||
import { hotels } from 'data/travel-agency/customer/hotel';
|
||||
import NavbarHome from 'components/navbars/travel-agency/NavbarHome';
|
||||
import HotelActions from 'components/modules/travel-agency/hotel/HotelActions';
|
||||
import TravelFooter from 'components/footers/TravelFooter';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { hotelNavItems } from 'data/travel-agency/resizableNav';
|
||||
import HomepageFilterOffcanvas from 'components/modules/travel-agency/hotel/HomepageFilterOffcanvas';
|
||||
|
||||
const HotelHomepage = () => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={hotelNavItems} />
|
||||
<section className="container-small py-0">
|
||||
<NavbarHome currentPage="Hotel" />
|
||||
</section>
|
||||
<HotelActions background={true} />
|
||||
<section className="container-medium py-0">
|
||||
<div className="py-6">
|
||||
<div className="d-flex">
|
||||
<Form.Select className="w-sm-auto me-4">
|
||||
<option>Sort by</option>
|
||||
<option>Best reviewed and lowest price</option>
|
||||
<option>Option 1</option>
|
||||
<option>Option 2</option>
|
||||
</Form.Select>
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
className="text-nowrap px-3 px-md-4 ms-auto me-2"
|
||||
>
|
||||
<FontAwesomeIcon icon={faMap} className="me-md-2" />
|
||||
<span className="d-none d-md-inline-block">Show in map</span>
|
||||
</Button>
|
||||
<Button
|
||||
variant="phoenix-secondary"
|
||||
className="text-nowrap px-3"
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faFilter} className="me-md-2" />
|
||||
<span className="d-none d-md-inline-block">Filters</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Row className="g-3 mb-6">
|
||||
{hotels.map((hotelInfo, index) => (
|
||||
<Col key={index} sm={6} lg={4} xl={3}>
|
||||
<HotelCard hotelInfo={hotelInfo} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</section>
|
||||
<TravelFooter />
|
||||
<HomepageFilterOffcanvas isOpen={isOpen} setIsOpen={setIsOpen} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HotelHomepage;
|
||||
117
src/pages/apps/travel-agency/landing/BestHotel.tsx
Normal file
117
src/pages/apps/travel-agency/landing/BestHotel.tsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import { faChevronRight, faStar } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import bgLeft29 from 'assets/img/bg/bg-left-29.png';
|
||||
|
||||
import Badge from 'components/base/Badge';
|
||||
import Button from 'components/base/Button';
|
||||
import { Card, Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import FeatherIcon from 'feather-icons-react';
|
||||
import { faHeart } from '@fortawesome/free-regular-svg-icons';
|
||||
import { hotelInterFace, hotelsData } from 'data/travel-agency/landing';
|
||||
|
||||
const HotelDetails = (data: hotelInterFace) => {
|
||||
const { image, rating, stay, name, located, price } = data;
|
||||
return (
|
||||
<Card className="card-img-shift border-0 mx-auto">
|
||||
<div className="rounded-3 overflow-hidden w-100 position-relative z-5">
|
||||
<img src={image} alt="" className="w-100" height="250" />
|
||||
<button className="btn btn-wish position-absolute top-0 end-0 mt-3 me-3">
|
||||
<FontAwesomeIcon icon={faHeart} />
|
||||
</button>
|
||||
</div>
|
||||
<Card.Body className="p-0">
|
||||
<div className="card-content">
|
||||
<div className="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-4">
|
||||
<div>
|
||||
<Badge
|
||||
variant="phoenix"
|
||||
bg={data.status.type}
|
||||
className="px-1 me-2"
|
||||
>
|
||||
{data.status.label}
|
||||
</Badge>
|
||||
<Badge variant="phoenix" bg={data.package.type} className="px-1">
|
||||
{data.package.label}
|
||||
</Badge>
|
||||
</div>
|
||||
<h6>
|
||||
<FontAwesomeIcon icon={faStar} className="text-warning me-1" />
|
||||
{rating} ({stay}k stay)
|
||||
</h6>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
to="#!"
|
||||
className="fw-bold fs-7 text-body-emphasis mb-2 text-primary-hover"
|
||||
>
|
||||
{name}
|
||||
</Link>
|
||||
<Link to="#!" className="fw-semibold text-body-tertiary mb-3 d-block">
|
||||
<FeatherIcon
|
||||
icon="map-pin"
|
||||
className="me-1"
|
||||
style={{ width: 16, height: 16 }}
|
||||
/>
|
||||
{located}
|
||||
</Link>
|
||||
<h6 className="fe-semibold text-body-tertiary d-flex align-items-center gap-1 mb-4">
|
||||
From
|
||||
<span className="fw-bolder fs-7 text-body-highlight">${price}</span>
|
||||
/ per night
|
||||
</h6>
|
||||
<Button variant="primary" className="px-5">
|
||||
Book Now
|
||||
</Button>
|
||||
</div>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
const BestHotel = () => {
|
||||
return (
|
||||
<section className="py-0">
|
||||
<div
|
||||
className="bg-holder d-none d-xl-block"
|
||||
style={{
|
||||
backgroundImage: `url(${bgLeft29})`,
|
||||
backgroundPosition: '-15%',
|
||||
backgroundSize: 'auto'
|
||||
}}
|
||||
/>
|
||||
<div className="position-relative container-medium">
|
||||
<h3 className="mb-2 text-body-emphasis text-center text-xl-start">
|
||||
The best of our hotel
|
||||
</h3>
|
||||
<div className="d-xl-flex justify-content-between mb-5 text-center">
|
||||
<p className="mb-0 text-body-tertiary">
|
||||
This list will help you get insights into how much you’ll need to
|
||||
spend to afford accommodation.
|
||||
</p>
|
||||
<Button variant="link" className="p-0 fs-8">
|
||||
View all
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronRight}
|
||||
transform="shrink-3"
|
||||
className="ms-2"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
<Row className="g-0 justify-content-center">
|
||||
<Col sm={11} md={8} lg={6} xl={12}>
|
||||
<Row className="gy-5 gx-xl-7 justify-content-between pe-4">
|
||||
{hotelsData.map((data, index) => (
|
||||
<Col xl={4} key={index}>
|
||||
<HotelDetails {...data} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default BestHotel;
|
||||
136
src/pages/apps/travel-agency/landing/BestPlaces.tsx
Normal file
136
src/pages/apps/travel-agency/landing/BestPlaces.tsx
Normal file
@@ -0,0 +1,136 @@
|
||||
import React from 'react';
|
||||
import bgLeft28 from 'assets/img/bg/bg-left-28.png';
|
||||
import bgRight28 from 'assets/img/bg/bg-right-28.png';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
faChevronLeft,
|
||||
faChevronRight,
|
||||
faHotel,
|
||||
faTreeCity
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Autoplay, Navigation } from 'swiper/modules';
|
||||
import SwiperCore from 'swiper';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { Container } from 'react-bootstrap';
|
||||
import { placesData } from 'data/travel-agency/landing';
|
||||
|
||||
const BestPlaces = () => {
|
||||
SwiperCore.use([Autoplay]);
|
||||
|
||||
return (
|
||||
<section className="pb-10 pt-0">
|
||||
<div
|
||||
className="bg-holder d-none d-md-block"
|
||||
style={{
|
||||
backgroundImage: `url(${bgLeft28})`,
|
||||
backgroundPosition: 'left 27%',
|
||||
backgroundSize: '7%'
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="bg-holder d-none d-md-block"
|
||||
style={{
|
||||
backgroundImage: `url(${bgRight28})`,
|
||||
backgroundPosition: 'right -25px',
|
||||
backgroundSize: '16%'
|
||||
}}
|
||||
/>
|
||||
<div className="container-medium text-center mb-11 position-relative">
|
||||
<h3 className="mb-2 text-body-emphasis">Travel more, spend less</h3>
|
||||
<p className="text-body-tertiary mb-0">
|
||||
Working with Phoenix means you’ll have all the plans and the perfect
|
||||
price list to help you plan.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* swiper */}
|
||||
<Container fluid className="px-sm-0">
|
||||
<div className="swiper-theme-container swiper-slide-nav-top">
|
||||
<div className="swiper-nav">
|
||||
<div className="swiper-button-next">
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronRight}
|
||||
className="text-primary"
|
||||
transform="shrink-3"
|
||||
/>
|
||||
</div>
|
||||
<div className="swiper-button-prev">
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronLeft}
|
||||
className="text-primary"
|
||||
transform="shrink-3"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Swiper
|
||||
loop
|
||||
centeredSlides
|
||||
autoplay
|
||||
centeredSlidesBounds
|
||||
spaceBetween={16}
|
||||
slidesPerView={1}
|
||||
speed={1500}
|
||||
breakpoints={{
|
||||
576: {
|
||||
slidesPerView: 'auto'
|
||||
}
|
||||
}}
|
||||
wrapperClass="swiper-wrapper"
|
||||
className="theme-slider"
|
||||
navigation={{
|
||||
nextEl: '.swiper-button-next',
|
||||
prevEl: '.swiper-button-prev'
|
||||
}}
|
||||
modules={[Navigation]}
|
||||
>
|
||||
{placesData.map((data, index) => (
|
||||
<SwiperSlide className="w-sm-auto" key={index}>
|
||||
<Link
|
||||
to="#!"
|
||||
className="position-relative rounded-3 overflow-hidden d-block"
|
||||
>
|
||||
<img
|
||||
src={data.img}
|
||||
alt=""
|
||||
className="w-100 w-sm-auto object-fit-cover"
|
||||
height={220}
|
||||
/>
|
||||
<div className="img-backdrop-faded">
|
||||
<div className="image-reveal-content mb-3">
|
||||
<div className="d-flex align-items-center gap-2 mb-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faHotel}
|
||||
className="text-secondary-lighter"
|
||||
/>
|
||||
<h6 className="mb-0 text-secondary-lighter fw-semibold">
|
||||
{data.hotels} Hotels
|
||||
</h6>
|
||||
</div>
|
||||
<div className="d-flex align-items-center gap-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faTreeCity}
|
||||
className="text-secondary-lighter"
|
||||
/>
|
||||
<h6 className="mb-0 text-secondary-lighter fw-semibold">
|
||||
{data.packages} Tour Package
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex align-items-center gap-2">
|
||||
<img src={data.flag} alt="" />
|
||||
<h4 className="mb-0 text-white">{data.country}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
</Container>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default BestPlaces;
|
||||
113
src/pages/apps/travel-agency/landing/Footer.tsx
Normal file
113
src/pages/apps/travel-agency/landing/Footer.tsx
Normal file
@@ -0,0 +1,113 @@
|
||||
import { Row, Col } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import logo1 from 'assets/img/icons/logo-1.png';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
faBehance,
|
||||
faFacebookF,
|
||||
faLinkedinIn,
|
||||
faTwitter
|
||||
} from '@fortawesome/free-brands-svg-icons';
|
||||
import bg41 from 'assets/img/bg/41.jpg';
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface footerItems {
|
||||
title: string;
|
||||
link: string;
|
||||
}
|
||||
const footerItems: footerItems[] = [
|
||||
{
|
||||
title: 'Home',
|
||||
link: '#!'
|
||||
},
|
||||
{
|
||||
title: 'About',
|
||||
link: '#!'
|
||||
},
|
||||
{
|
||||
title: 'Contact',
|
||||
link: '#!'
|
||||
},
|
||||
{
|
||||
title: 'FAQ',
|
||||
link: '#!'
|
||||
},
|
||||
{
|
||||
title: 'Gallery',
|
||||
link: '#!'
|
||||
}
|
||||
];
|
||||
|
||||
const Footer = () => {
|
||||
return (
|
||||
<section className="booking-footer pb-6 pb-md-11 pt-15">
|
||||
<div
|
||||
className="bg-holder"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(
|
||||
0deg,
|
||||
rgba(0, 0, 0, 0.8) 0%,
|
||||
rgba(0, 0, 0, 0.8) 100%
|
||||
),
|
||||
url(${bg41})`,
|
||||
backgroundPosition: 'center',
|
||||
backgroundSize: 'cover',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
zIndex: '-1'
|
||||
}}
|
||||
/>
|
||||
<div className="container-medium">
|
||||
<Row className="gy-3 justify-content-between align-items-center">
|
||||
<Col xs="auto">
|
||||
<Link to="#!">
|
||||
<img src={logo1} alt="" />
|
||||
</Link>
|
||||
</Col>
|
||||
<Col xs="auto">
|
||||
<ul className="mb-0 list-unstyled d-flex flex-wrap">
|
||||
{footerItems.map((item, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className={classNames('', {
|
||||
'me-sm-5 me-3': index !== footerItems.length - 1
|
||||
})}
|
||||
>
|
||||
<Link to={item.link} className="fs-8 fw-bold text-white">
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Col>
|
||||
</Row>
|
||||
<hr className="my-4" />
|
||||
<Row className="gy-3 justify-content-between">
|
||||
<Col xs="auto">
|
||||
<Link to="#!" className="me-4 text-white">
|
||||
<FontAwesomeIcon icon={faFacebookF} />
|
||||
</Link>
|
||||
<Link to="#!" className="me-4 text-white">
|
||||
<FontAwesomeIcon icon={faTwitter} />
|
||||
</Link>
|
||||
<Link to="#!" className="me-4 text-white">
|
||||
<FontAwesomeIcon icon={faLinkedinIn} />
|
||||
</Link>
|
||||
<Link to="#!" className="text-white">
|
||||
<FontAwesomeIcon icon={faBehance} />
|
||||
</Link>
|
||||
</Col>
|
||||
<Col xs="auto">
|
||||
<p className="mb-0 text-white">
|
||||
Thank you for creating with Phoenix | 2023 ©{' '}
|
||||
<Link to="https://themewagon.com/" className="text-white">
|
||||
Themewagon
|
||||
</Link>
|
||||
</p>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
148
src/pages/apps/travel-agency/landing/Gallery.tsx
Normal file
148
src/pages/apps/travel-agency/landing/Gallery.tsx
Normal file
@@ -0,0 +1,148 @@
|
||||
import bgLeft30 from 'assets/img/bg/bg-left-30.png';
|
||||
import bgRight30 from 'assets/img/bg/bg-right-30.png';
|
||||
import IsotopeNav from 'components/navs/IsotopeNav';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faArrowRight } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faHeart } from '@fortawesome/free-regular-svg-icons';
|
||||
import Rating from 'components/base/Rating';
|
||||
import Button from 'components/base/Button';
|
||||
import { GalleryInterface, galleryItems } from 'data/travel-agency/landing';
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
eventKey: 'tokyo',
|
||||
label: 'Tokyo'
|
||||
},
|
||||
{
|
||||
eventKey: 'bali',
|
||||
label: 'Bali'
|
||||
},
|
||||
{
|
||||
eventKey: 'sydney',
|
||||
label: 'Sydney'
|
||||
},
|
||||
{
|
||||
eventKey: 'paris',
|
||||
label: 'Paris'
|
||||
}
|
||||
];
|
||||
|
||||
const GalleryItem = ({ galleryItem }: { galleryItem: GalleryInterface }) => {
|
||||
return (
|
||||
<Col xs={12} className="w-100">
|
||||
<div className="img-zoom-hover-lg rounded-2 overflow-hidden position-relative">
|
||||
<Link to="#!">
|
||||
<img
|
||||
className="w-100 object-fit-cover"
|
||||
height={220}
|
||||
src={galleryItem.img}
|
||||
alt=""
|
||||
/>
|
||||
</Link>
|
||||
<button className="btn btn-wish position-absolute top-0 end-0 mt-3 me-3">
|
||||
<FontAwesomeIcon icon={faHeart} />
|
||||
</button>
|
||||
<div className="backdrop-faded">
|
||||
<Link to="#!" className="fw-bolder fs-7 text-white streched-link">
|
||||
{galleryItem.location}
|
||||
</Link>
|
||||
<h5 className="text-light mb-0">
|
||||
{/* <FontAwesomeIcon icon={faStar} className="text-warning me-1" /> */}
|
||||
<Rating
|
||||
iconClass="me-1 fs-8 mb-1"
|
||||
initialValue={1}
|
||||
iconsCount={1}
|
||||
allowFraction={false}
|
||||
/>
|
||||
{galleryItem.rating}
|
||||
<span className="fs-10">/5 </span>({galleryItem.review}k review)
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
);
|
||||
};
|
||||
|
||||
const Gallery = () => {
|
||||
const [selectedCategory, setSelectedCategory] = useState(
|
||||
galleryItems[0].category
|
||||
);
|
||||
const initialgallery = galleryItems.filter(item =>
|
||||
item.category.includes(selectedCategory)
|
||||
);
|
||||
const [images, setImages] = useState(initialgallery);
|
||||
|
||||
const handleNavItemSelect = (category: string | null) => {
|
||||
setSelectedCategory(category || galleryItems[0].category);
|
||||
setImages(
|
||||
galleryItems.filter(item =>
|
||||
category ? item.category.includes(category) : true
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="py-10 overflow-hidden">
|
||||
<div
|
||||
className="bg-holder d-none d-xl-block"
|
||||
style={{
|
||||
backgroundImage: `url(${bgLeft30})`,
|
||||
backgroundPosition: 'left',
|
||||
backgroundSize: '40%',
|
||||
zIndex: '1'
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="bg-holder d-none d-xl-block"
|
||||
style={{
|
||||
backgroundImage: `url(${bgRight30})`,
|
||||
backgroundPosition: 'right 25px',
|
||||
backgroundSize: '26%',
|
||||
zIndex: '1'
|
||||
}}
|
||||
/>
|
||||
<div className="bg-booking-gallery" />
|
||||
<div className="container-medium position-relative z-2">
|
||||
<h3 className="mb-2 text-body-emphasis text-center">
|
||||
Popular Attractions
|
||||
</h3>
|
||||
<p className="mb-0 text-body-tertiary text-center mb-5">
|
||||
Explore the most popular and frequently visited destinations around
|
||||
the world
|
||||
</p>
|
||||
<IsotopeNav
|
||||
navItems={navItems}
|
||||
className="mb-5 justify-content-center w-max-content mx-auto"
|
||||
onSelect={handleNavItemSelect}
|
||||
/>
|
||||
<div className="row g-0 justify-content-center">
|
||||
<Col md={9} lg={7} xl={5}>
|
||||
<Row className="gx-0 gy-3">
|
||||
{images.map(gallery => (
|
||||
<GalleryItem galleryItem={gallery} key={gallery.img} />
|
||||
))}
|
||||
</Row>
|
||||
<div className="d-flex align-items-center justify-content-center gap-3 mt-4">
|
||||
<h5 className="mb-0">Explore more popular destination</h5>
|
||||
<div className="btn-ping">
|
||||
<div className="btn-ping-bg" />
|
||||
<Button
|
||||
variant="link"
|
||||
className="border p-0 fs-8 d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<FontAwesomeIcon icon={faArrowRight} />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Gallery;
|
||||
82
src/pages/apps/travel-agency/landing/GetApp.tsx
Normal file
82
src/pages/apps/travel-agency/landing/GetApp.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import bgLeft33 from 'assets/img/bg/bg-left-33.png';
|
||||
import bgRight33 from 'assets/img/bg/bg-right-33.png';
|
||||
import iPhone from 'assets/img/spot-illustrations/i-phone.png';
|
||||
import iPhoneDark from 'assets/img/spot-illustrations/i-phone-dark.png';
|
||||
import spotIllustration41 from 'assets/img/spot-illustrations/41.png';
|
||||
import spotIllustrationDark41 from 'assets/img/spot-illustrations/dark_41.png';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import playStore from 'assets/img/generic/play-store.png';
|
||||
import appStore from 'assets/img/generic/app-store.png';
|
||||
|
||||
const GetApp = () => {
|
||||
return (
|
||||
<section className="pb-10 pt-9">
|
||||
<div
|
||||
className="bg-holder d-none d-xl-block"
|
||||
style={{
|
||||
backgroundImage: `url(${bgLeft33})`,
|
||||
backgroundPosition: '-8% 38px',
|
||||
backgroundSize: 'auto'
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="bg-holder d-none d-xl-block"
|
||||
style={{
|
||||
backgroundImage: `url(${bgRight33})`,
|
||||
backgroundPosition: 'right',
|
||||
backgroundSize: '18%'
|
||||
}}
|
||||
/>
|
||||
<div className="bg-get-app" />
|
||||
<div className="container-medium position-relative">
|
||||
<Row className="g-0 justify-content-center">
|
||||
<Col lg={10} xl={8} xxl={7}>
|
||||
<div className="d-md-flex align-items-center gap-5 text-center text-md-start">
|
||||
<img
|
||||
src={iPhone}
|
||||
alt=""
|
||||
style={{ maxHeight: '540px' }}
|
||||
className="d-dark-none img-fluid"
|
||||
/>
|
||||
<img
|
||||
src={iPhoneDark}
|
||||
alt=""
|
||||
style={{ maxHeight: '540px' }}
|
||||
className="d-light-none img-fluid"
|
||||
/>
|
||||
<div className="mt-5 mt-md-0">
|
||||
<div className="d-none d-md-block">
|
||||
<img
|
||||
src={spotIllustration41}
|
||||
alt=""
|
||||
width={200}
|
||||
className="d-dark-none"
|
||||
/>
|
||||
<img
|
||||
src={spotIllustrationDark41}
|
||||
alt=""
|
||||
width={200}
|
||||
className="d-light-none"
|
||||
/>
|
||||
</div>
|
||||
<h3 className="fw-bolder mt-4">Get The App Now</h3>
|
||||
<p className="text-body-tertiary">
|
||||
Designed to provide the best user experience possible to all
|
||||
our customers with activities ranging from anything thinkable
|
||||
to the unthinkables.
|
||||
</p>
|
||||
<Link to="#!">
|
||||
<img src={playStore} alt="" height={32} className="me-2" />
|
||||
<img src={appStore} alt="" height={32} />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default GetApp;
|
||||
91
src/pages/apps/travel-agency/landing/HeroHeader.tsx
Normal file
91
src/pages/apps/travel-agency/landing/HeroHeader.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import travelImg from 'assets/video/travel.png';
|
||||
import travelVideo from 'assets/video/travel.mp4';
|
||||
import { Dropdown, Form, InputGroup } from 'react-bootstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
faChevronDown,
|
||||
faLocationDot
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ReactTyped } from 'react-typed';
|
||||
|
||||
const HeroHeader = () => {
|
||||
return (
|
||||
<div className="booking-hero-header d-flex align-items-center">
|
||||
<div
|
||||
className="bg-holder overlay bg-opacity-50"
|
||||
style={{
|
||||
backgroundImage: `url(${travelImg})`,
|
||||
backgroundPosition: 'left bottom',
|
||||
backgroundSize: 'auto'
|
||||
}}
|
||||
>
|
||||
<video className="bg-video" autoPlay loop muted src={travelVideo} />
|
||||
</div>
|
||||
<div className="container-medium position-relative z-5">
|
||||
<h2 className="text-secondary-lighter fs-5 fs-md-3 fw-normal mb-3">
|
||||
Where is your
|
||||
</h2>
|
||||
<h1 className="fs-4 fs-md-1 text-white fw-normal mb-6 overflow-hidden">
|
||||
NEXT{' '}
|
||||
<ReactTyped
|
||||
strings={[
|
||||
'<span class=text-primary>TRIP!</span>',
|
||||
'<span class=text-warning>TOUR!</span>',
|
||||
'<span class=text-info>SOJOURN!</span>',
|
||||
'<span class=text-success>VACAY!</span>'
|
||||
]}
|
||||
typeSpeed={70}
|
||||
backSpeed={70}
|
||||
loop
|
||||
backDelay={1000}
|
||||
/>
|
||||
</h1>
|
||||
<InputGroup className="rounded-2 py-1 ps-2 w-lg-50 border border-light">
|
||||
<div className="form-icon-container flex-1 d-flex align-items-center">
|
||||
<FontAwesomeIcon
|
||||
icon={faLocationDot}
|
||||
className="form-icon text-danger-light"
|
||||
/>
|
||||
<Form.Control
|
||||
type="text"
|
||||
placeholder="Search Destination"
|
||||
className="form-icon-input bg-transparent border-0 outline-none fs-8 fs-md-7 text-secondary-light"
|
||||
/>
|
||||
</div>
|
||||
{/* dropdwon class not added */}
|
||||
<Dropdown align="end">
|
||||
<div className="d-flex align-items-center">
|
||||
<Dropdown.Toggle
|
||||
as="button"
|
||||
id="dropdown-basic"
|
||||
className="btn dropdown-caret-none py-0 bg-transparent text-secondary-light fs-8 fs-md-7 fw-semibold border-0 border-start border-light rounded-0"
|
||||
>
|
||||
Flight
|
||||
<FontAwesomeIcon
|
||||
className="ms-2"
|
||||
icon={faChevronDown}
|
||||
transform="down-1 shrink-4"
|
||||
/>
|
||||
</Dropdown.Toggle>
|
||||
|
||||
<Dropdown.Menu data-bs-theme="dark" className="dropdown-menu-end">
|
||||
<Dropdown.Item to="#!" as={Link}>
|
||||
Flight
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item to="#!" as={Link}>
|
||||
Trip
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item to="#!" as={Link}>
|
||||
Hotel
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</InputGroup>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeroHeader;
|
||||
51
src/pages/apps/travel-agency/landing/Landing.tsx
Normal file
51
src/pages/apps/travel-agency/landing/Landing.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import useSettingsMountEffect from 'hooks/useSettingsMountEffect';
|
||||
import HeroHeader from './HeroHeader';
|
||||
import SeasonOfTour from './SeasonOfTour';
|
||||
import BestPlaces from './BestPlaces';
|
||||
import BestHotel from './BestHotel';
|
||||
import Gallery from './Gallery';
|
||||
import LatestPosts from './LatestPosts';
|
||||
import LatestPhotos from './LatestPhotos';
|
||||
import GetApp from './GetApp';
|
||||
import TravelCta from 'components/cta/TravelCta';
|
||||
|
||||
const Landing = () => {
|
||||
useSettingsMountEffect({
|
||||
disableNavigationType: true,
|
||||
disableHorizontalNavbarAppearance: true,
|
||||
disableVerticalNavbarAppearance: true,
|
||||
disableHorizontalNavbarShape: true
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
document.body.classList.add('bg-body-emphasis');
|
||||
document.body.setAttribute(
|
||||
'style',
|
||||
document.body.getAttribute('style')
|
||||
? document.body.getAttribute('style') +
|
||||
'; --phoenix-scroll-margin-top: 1.2rem'
|
||||
: '--phoenix-scroll-margin-top: 1.2rem'
|
||||
);
|
||||
return () => {
|
||||
document.body.classList.remove('bg-body-emphasis');
|
||||
document.body.removeAttribute('style');
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<HeroHeader />
|
||||
<SeasonOfTour />
|
||||
<BestPlaces />
|
||||
<BestHotel />
|
||||
<Gallery />
|
||||
<LatestPosts />
|
||||
<TravelCta />
|
||||
<LatestPhotos />
|
||||
<GetApp />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Landing;
|
||||
87
src/pages/apps/travel-agency/landing/LatestPhotos.tsx
Normal file
87
src/pages/apps/travel-agency/landing/LatestPhotos.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import { faLocationDot } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import gallery51 from 'assets/img/gallery/51.png';
|
||||
import gallery52 from 'assets/img/gallery/52.png';
|
||||
import gallery53 from 'assets/img/gallery/53.png';
|
||||
import gallery54 from 'assets/img/gallery/54.png';
|
||||
import gallery55 from 'assets/img/gallery/55.png';
|
||||
import gallery56 from 'assets/img/gallery/56.png';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
interface photos {
|
||||
img: string;
|
||||
location: string;
|
||||
}
|
||||
const photos: photos[] = [
|
||||
{
|
||||
img: gallery51,
|
||||
location: 'Bali Indonesia'
|
||||
},
|
||||
{
|
||||
img: gallery52,
|
||||
location: 'Barcelona'
|
||||
},
|
||||
{
|
||||
img: gallery53,
|
||||
location: 'Bali Indonesia'
|
||||
},
|
||||
{
|
||||
img: gallery54,
|
||||
location: 'Sydney'
|
||||
},
|
||||
{
|
||||
img: gallery55,
|
||||
location: 'Great Barrier Reef'
|
||||
},
|
||||
{
|
||||
img: gallery56,
|
||||
location: 'Grand Canyon'
|
||||
}
|
||||
];
|
||||
|
||||
const LatestPhotos = () => {
|
||||
return (
|
||||
<section className="pb-7 pt-0">
|
||||
<div className="container-medium">
|
||||
<div className="text-center mb-5">
|
||||
<h3 className="mb-2 text-body-emphasis">
|
||||
Latest photos from tourists
|
||||
</h3>
|
||||
<p className="mb-0 text-body-tertiary">
|
||||
See how our tourists enjoyed their trip from images captured by them
|
||||
with Team Phoenix!
|
||||
</p>
|
||||
</div>
|
||||
<Row className="g-3">
|
||||
{photos.map((item, index) => (
|
||||
<Col md={6} xl={4} key={index}>
|
||||
<div className="img-zoom-hover position-relative h-100 rounded-3 overflow-hidden">
|
||||
<Link to="#!">
|
||||
<img
|
||||
className="w-100 h-100 object-fit-cover"
|
||||
src={item.img}
|
||||
alt=""
|
||||
/>
|
||||
</Link>
|
||||
<div className="backdrop-faded">
|
||||
<Link
|
||||
to="#!"
|
||||
className="w-semibold mb-0 text-secondary-lighter stretched-link"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faLocationDot}
|
||||
className="text-secondary-lighter me-2"
|
||||
/>
|
||||
{item.location}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default LatestPhotos;
|
||||
184
src/pages/apps/travel-agency/landing/LatestPosts.tsx
Normal file
184
src/pages/apps/travel-agency/landing/LatestPosts.tsx
Normal file
@@ -0,0 +1,184 @@
|
||||
import FeatherIcon from 'feather-icons-react';
|
||||
import bgLeft31 from 'assets/img/bg/bg-left-31.png';
|
||||
import bgRight31 from 'assets/img/bg/bg-right-31.png';
|
||||
import gallery48 from 'assets/img/gallery/48.png';
|
||||
import gallery49 from 'assets/img/gallery/49.png';
|
||||
import gallery50 from 'assets/img/gallery/50.png';
|
||||
import gallery64 from 'assets/img/gallery/64.png';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import SwiperCore from 'swiper';
|
||||
import { Autoplay, Navigation } from 'swiper/modules';
|
||||
import Rating from 'components/base/Rating';
|
||||
import Button from 'components/base/Button';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
faChevronLeft,
|
||||
faChevronRight
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
SwiperCore.use([Autoplay]);
|
||||
interface posts {
|
||||
title: string;
|
||||
date: string;
|
||||
rating: number;
|
||||
img: string;
|
||||
}
|
||||
const posts: posts[] = [
|
||||
{
|
||||
title: "Beautiful Frence, Let's Travelling!",
|
||||
date: 'Monday, Nov 07, 2022',
|
||||
rating: 4.8,
|
||||
img: gallery48
|
||||
},
|
||||
{
|
||||
title: 'Man Standing on Watching Mountain',
|
||||
date: 'Monday, Nov 06, 2022',
|
||||
rating: 4.5,
|
||||
img: gallery49
|
||||
},
|
||||
{
|
||||
title: "Beautiful Bali Indonesia, Let's Travelling!",
|
||||
date: 'Monday, Nov 05, 2022',
|
||||
rating: 4.2,
|
||||
img: gallery50
|
||||
},
|
||||
{
|
||||
title: 'Chasing sunsets, making memories worldwide.',
|
||||
date: 'Monday, Nov 04, 2022',
|
||||
rating: 4.5,
|
||||
img: gallery64
|
||||
}
|
||||
];
|
||||
const LatestPosts = () => {
|
||||
return (
|
||||
<section className="pb-7 pt-0 overflow-x-hidden">
|
||||
<div
|
||||
className="bg-holder d-none d-xl-block"
|
||||
style={{
|
||||
backgroundImage: `url(${bgLeft31})`,
|
||||
backgroundPosition: 'left',
|
||||
backgroundSize: '22%',
|
||||
zIndex: '1'
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="bg-holder d-none d-xl-block"
|
||||
style={{
|
||||
backgroundImage: `url(${bgRight31})`,
|
||||
backgroundPosition: 'right bottom',
|
||||
backgroundSize: '15%',
|
||||
zIndex: '1'
|
||||
}}
|
||||
/>
|
||||
<div className="bg-latest-posts" />
|
||||
<div className="container-medium text-center position-relative z-2">
|
||||
<h3 className="mb-2 text-body-emphasis">
|
||||
Our Latest Posts For Travellers
|
||||
</h3>
|
||||
<p className="mb-0 text-body-tertiary mb-13">
|
||||
Find the best travel memories from our past tours and get a clear idea
|
||||
of what we do.
|
||||
</p>
|
||||
</div>
|
||||
<div className="swiper-theme-container swiper-zooming-slider">
|
||||
<div className="swiper-container ">
|
||||
<Swiper
|
||||
loop
|
||||
centeredSlides
|
||||
autoplay
|
||||
centeredSlidesBounds
|
||||
spaceBetween={32}
|
||||
slidesPerView={1.3}
|
||||
speed={2000}
|
||||
navigation={{
|
||||
nextEl: '.swiper-button-next',
|
||||
prevEl: '.swiper-button-prev'
|
||||
}}
|
||||
modules={[Navigation]}
|
||||
breakpoints={{
|
||||
540: {
|
||||
slidesPerView: 1.5
|
||||
},
|
||||
768: {
|
||||
slidesPerView: 1.8
|
||||
},
|
||||
1200: {
|
||||
slidesPerView: 2
|
||||
},
|
||||
1530: {
|
||||
slidesPerView: 2.8
|
||||
}
|
||||
}}
|
||||
wrapperClass="swiper-wrapper"
|
||||
className="theme-slider swiper-container overflow-visible"
|
||||
>
|
||||
{posts.map((data, index) => (
|
||||
<SwiperSlide className="rounded-3 overflow-hidden" key={index}>
|
||||
<div className="position-relative w-100 h-100">
|
||||
<img
|
||||
src={data.img}
|
||||
className="w-100 h-100 object-fit-cover"
|
||||
alt=""
|
||||
/>
|
||||
<div className="backdrop-faded p-4 p-md-6">
|
||||
<div className="d-flex align-items-center mb-2">
|
||||
<FeatherIcon
|
||||
icon="calendar"
|
||||
className="text-secondary-lighter me-2"
|
||||
style={{ width: 16 }}
|
||||
/>
|
||||
<h6 className="mb-0 fw-semibold text-secondary-lighter pe-3 me-3 border-end">
|
||||
{data.date}
|
||||
</h6>
|
||||
<Rating
|
||||
iconClass="text-warning fs-9 me-2"
|
||||
initialValue={1}
|
||||
iconsCount={1}
|
||||
allowFraction={false}
|
||||
/>
|
||||
<h6 className="mb-0 text-secondary-lighter fw-semibold">
|
||||
{data.rating}
|
||||
</h6>
|
||||
</div>
|
||||
<Link to="#!" className="text-white fw-bold fs-7">
|
||||
{data.title}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
<div className="swiper-nav">
|
||||
<div className="swiper-button-next">
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronRight}
|
||||
className="text-primary"
|
||||
transform="shrink-3"
|
||||
/>
|
||||
</div>
|
||||
<div className="swiper-button-prev">
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronLeft}
|
||||
className="text-primary"
|
||||
transform="shrink-3"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-center mt-12 position-relative z-2">
|
||||
<Button variant="link" className="p-0 fs-8">
|
||||
View all
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronRight}
|
||||
className="ms-2"
|
||||
transform="shrink-2"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default LatestPosts;
|
||||
139
src/pages/apps/travel-agency/landing/SeasonOfTour.tsx
Normal file
139
src/pages/apps/travel-agency/landing/SeasonOfTour.tsx
Normal file
@@ -0,0 +1,139 @@
|
||||
import React, { FC, HTMLAttributes } from 'react';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import bgLeft27 from 'assets/img/bg/bg-left-27.png';
|
||||
import bgRight27 from 'assets/img/bg/bg-right-27.png';
|
||||
import gallery35 from 'assets/img/gallery/35.png';
|
||||
import gallery36 from 'assets/img/gallery/36.png';
|
||||
import gallery37 from 'assets/img/gallery/37.png';
|
||||
import gallery38 from 'assets/img/gallery/38.png';
|
||||
import Button from 'components/base/Button';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faChevronRight } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
interface ImageZoomHoverCard extends HTMLAttributes<HTMLDivElement> {
|
||||
src: string;
|
||||
title: string;
|
||||
subTitle: string;
|
||||
imgClass?: string;
|
||||
}
|
||||
|
||||
const ImageZoomHoverCard: FC<ImageZoomHoverCard> = ({
|
||||
src,
|
||||
title,
|
||||
subTitle,
|
||||
imgClass = 'h-100',
|
||||
...rest
|
||||
}: ImageZoomHoverCard) => {
|
||||
return (
|
||||
<div className="img-zoom-hover position-relative h-100 rounded-3 overflow-hidden">
|
||||
<Link to="#!">
|
||||
<img
|
||||
className={`w-100 object-fit-cover ${imgClass}`}
|
||||
src={src}
|
||||
alt=""
|
||||
{...rest}
|
||||
/>
|
||||
</Link>
|
||||
<div className="backdrop-faded">
|
||||
<Link to="#!" className="fw-bold fs-7 text-white streched-link">
|
||||
{title}
|
||||
</Link>
|
||||
<p className="mb-0 text-white fs-9">{subTitle}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SeasonOfTour = () => {
|
||||
return (
|
||||
<section className="pt-6 pt-md-10 pb-10">
|
||||
<div className="container-medium">
|
||||
<div
|
||||
className="bg-holder d-none d-xl-block bg-left"
|
||||
style={{
|
||||
backgroundImage: `url(${bgLeft27})`,
|
||||
backgroundSize: 'auto'
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="bg-holder d-none d-xl-block bg-right"
|
||||
style={{
|
||||
backgroundImage: `url(${bgRight27})`,
|
||||
backgroundSize: 'auto'
|
||||
}}
|
||||
/>
|
||||
<Row className="g-3 position-relative">
|
||||
<Col lg={6}>
|
||||
<Row className="g-3">
|
||||
<Col md={7}>
|
||||
<h4 className="fw-semibold mb-3">Season of </h4>
|
||||
<h2 className="fs-4 fw-semibold mb-3 mb-md-4">
|
||||
Tour &{' '}
|
||||
<span className="text-primary-light fw-bold">Travel</span>
|
||||
</h2>
|
||||
<p className="mb-3 mb-md-0 text-body-tertiary">
|
||||
This is the perfect season for tours and travels. At Phoenix,
|
||||
you can easily select the best travel option for your next
|
||||
vacation
|
||||
<span className="d-none d-lg-inline-block d-xl-none">
|
||||
...
|
||||
</span>
|
||||
<span className="d-lg-none d-xl-inline">
|
||||
This will help you with the pricing that you’ll need, the
|
||||
accommodation facilities, food and beverages, and water
|
||||
rides.
|
||||
</span>
|
||||
</p>
|
||||
</Col>
|
||||
|
||||
<Col xs={6} md={5}>
|
||||
<ImageZoomHoverCard
|
||||
src={gallery35}
|
||||
title="New Zealand"
|
||||
subTitle="17 Hotels"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={6} md={5}>
|
||||
<ImageZoomHoverCard
|
||||
src={gallery36}
|
||||
title="London"
|
||||
subTitle="17 Hotels"
|
||||
/>
|
||||
</Col>
|
||||
<Col md={7}>
|
||||
<ImageZoomHoverCard
|
||||
src={gallery37}
|
||||
title="Maui"
|
||||
subTitle="14 Hotels"
|
||||
imgClass="h-md-100"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col lg={6}>
|
||||
<div className="d-flex flex-column gap-3 h-100">
|
||||
<ImageZoomHoverCard
|
||||
src={gallery38}
|
||||
title="Bali, Indonesia"
|
||||
subTitle="51 Hotels"
|
||||
imgClass="h-lg-100"
|
||||
style={{ height: 220 }}
|
||||
/>
|
||||
<Button variant="primary" className="w-100 py-3 fs-8">
|
||||
Explore more
|
||||
<FontAwesomeIcon
|
||||
className="ms-2"
|
||||
icon={faChevronRight}
|
||||
transform="down-2"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default SeasonOfTour;
|
||||
100
src/pages/apps/travel-agency/landing/TopNav copy.tsx
Normal file
100
src/pages/apps/travel-agency/landing/TopNav copy.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
import { faWhatsapp } from '@fortawesome/free-brands-svg-icons';
|
||||
import { faEnvelope } from '@fortawesome/free-regular-svg-icons';
|
||||
import {
|
||||
IconDefinition,
|
||||
faArrowRightToBracket,
|
||||
faEllipsisH
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import React from 'react';
|
||||
import { Dropdown } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const TopNav = () => {
|
||||
interface navItems {
|
||||
title: string;
|
||||
link: string;
|
||||
icon?: IconDefinition;
|
||||
transform?: string;
|
||||
}
|
||||
const navItems: navItems[] = [
|
||||
{
|
||||
title: 'Become a Host',
|
||||
link: '#!'
|
||||
},
|
||||
{
|
||||
title: 'Blog',
|
||||
link: '#!'
|
||||
},
|
||||
{
|
||||
title: 'Career',
|
||||
link: '#!'
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Support',
|
||||
link: 'mailto:example@gmail.com',
|
||||
icon: faEnvelope,
|
||||
transform: 'down-1'
|
||||
},
|
||||
{
|
||||
title: '+01 123 581321',
|
||||
link: 'tel:+01123581321',
|
||||
icon: faWhatsapp
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="bg-primary-subtle py-2">
|
||||
<div className="container-medium d-flex align-items-center justify-content-between">
|
||||
<Button href="#!" variant="link" className="text-body p-0">
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowRightToBracket}
|
||||
className="me-2"
|
||||
transform="down-1"
|
||||
/>
|
||||
Agent Login
|
||||
</Button>
|
||||
<Dropdown>
|
||||
{/* <Button size="sm" className="p-0 d-md-none fs-8"></Button> */}
|
||||
<Dropdown.Toggle
|
||||
size="sm"
|
||||
variant=""
|
||||
className="p-0 d-md-none fs-8 dropdown-caret-none"
|
||||
>
|
||||
<FontAwesomeIcon icon={faEllipsisH} />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu style={{ zIndex: 9999 }}>
|
||||
<Dropdown.Item href="">Become a Host</Dropdown.Item>
|
||||
<Dropdown.Item href="">Blog</Dropdown.Item>
|
||||
<Dropdown.Item href="">Career</Dropdown.Item>
|
||||
<Dropdown.Item href="">Support</Dropdown.Item>
|
||||
<Dropdown.Item href="">+01 123 581321</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<ul className="d-none d-md-flex gap-5 list-unstyled mb-0">
|
||||
{navItems.map((item, index) => (
|
||||
<li key={index}>
|
||||
<Link
|
||||
to={item.link}
|
||||
className="lh-1 text-body-tertiary fw-semibold fs-9"
|
||||
>
|
||||
{item.icon && (
|
||||
<FontAwesomeIcon
|
||||
icon={item.icon}
|
||||
transform={item.transform || undefined}
|
||||
className="me-2"
|
||||
/>
|
||||
)}
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopNav;
|
||||
84
src/pages/apps/travel-agency/landing/TopNav.tsx
Normal file
84
src/pages/apps/travel-agency/landing/TopNav.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import {
|
||||
faArrowRightToBracket,
|
||||
faEllipsisH,
|
||||
IconDefinition
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import { Dropdown } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const TopNav = () => {
|
||||
interface navItems {
|
||||
title: string;
|
||||
link: string;
|
||||
icon?: IconDefinition;
|
||||
transform?: string;
|
||||
}
|
||||
const navItems: navItems[] = [
|
||||
{
|
||||
title: 'Homepage',
|
||||
link: '#!'
|
||||
},
|
||||
{
|
||||
title: 'Booking',
|
||||
link: '#!'
|
||||
},
|
||||
{
|
||||
title: 'Payment',
|
||||
link: '#!'
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="bg-primary-subtle py-2">
|
||||
<div className="container-medium d-flex align-items-center justify-content-between">
|
||||
<Button href="#!" variant="link" className="text-body p-0">
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowRightToBracket}
|
||||
className="me-2"
|
||||
transform="down-1"
|
||||
/>
|
||||
Agent Login
|
||||
</Button>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
size="sm"
|
||||
variant=""
|
||||
className="p-0 d-md-none fs-8 dropdown-caret-none"
|
||||
>
|
||||
<FontAwesomeIcon icon={faEllipsisH} />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu style={{ zIndex: 9999 }}>
|
||||
<Dropdown.Item href="">Become a Host</Dropdown.Item>
|
||||
<Dropdown.Item href="">Blog</Dropdown.Item>
|
||||
<Dropdown.Item href="">Career</Dropdown.Item>
|
||||
<Dropdown.Item href="">Support</Dropdown.Item>
|
||||
<Dropdown.Item href="">+01 123 581321</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<ul className="d-none d-md-flex gap-5 list-unstyled mb-0">
|
||||
{navItems.map((item, index) => (
|
||||
<li key={index}>
|
||||
<Link
|
||||
to={item.link}
|
||||
className="lh-1 text-body-tertiary fw-semibold fs-9"
|
||||
>
|
||||
{item.icon && (
|
||||
<FontAwesomeIcon
|
||||
icon={item.icon}
|
||||
transform={item.transform || undefined}
|
||||
className="me-2"
|
||||
/>
|
||||
)}
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopNav;
|
||||
91
src/pages/apps/travel-agency/landing/TravelAgencyFooter.tsx
Normal file
91
src/pages/apps/travel-agency/landing/TravelAgencyFooter.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import React from 'react';
|
||||
import { Navbar, Container, Row, Col } from 'react-bootstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { IconDefinition } from '@fortawesome/free-brands-svg-icons';
|
||||
import { faWhatsapp } from '@fortawesome/free-brands-svg-icons';
|
||||
import { faEnvelope } from '@fortawesome/free-regular-svg-icons';
|
||||
import { Link } from 'react-router-dom';
|
||||
import Logo from 'components/common/Logo';
|
||||
import classNames from 'classnames';
|
||||
import Footer from 'components/footers/Footer';
|
||||
|
||||
interface TravelAgencyFooterProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface navItems {
|
||||
title: string;
|
||||
link: string;
|
||||
icon?: IconDefinition;
|
||||
transform?: string;
|
||||
}
|
||||
|
||||
const navItems: navItems[] = [
|
||||
{
|
||||
title: 'Become a Host',
|
||||
link: '#!'
|
||||
},
|
||||
{
|
||||
title: 'Blog',
|
||||
link: '#!'
|
||||
},
|
||||
{
|
||||
title: 'Career',
|
||||
link: '#!'
|
||||
},
|
||||
|
||||
{
|
||||
title: 'Support',
|
||||
link: 'mailto:example@gmail.com',
|
||||
icon: faEnvelope,
|
||||
transform: 'down-1'
|
||||
},
|
||||
{
|
||||
title: '+01 123 581321',
|
||||
link: 'tel:+01123581321',
|
||||
icon: faWhatsapp
|
||||
}
|
||||
];
|
||||
|
||||
const TravelAgencyFooter = ({ className }: TravelAgencyFooterProps) => {
|
||||
return (
|
||||
<Container fluid="medium">
|
||||
<Row
|
||||
className={classNames(
|
||||
'flex-center justify-content-md-between align-items-md-center mb-3 gy-2',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<Col xs="auto">
|
||||
<Navbar.Brand as={Link} to={'/'} className="flex-1 flex-grow-0">
|
||||
<Logo />
|
||||
</Navbar.Brand>
|
||||
</Col>
|
||||
<Col xs="auto">
|
||||
<ul className="d-flex flex-center flex-wrap gap-x-5 gap-y-1 list-unstyled mb-0">
|
||||
{navItems.map((item, index) => (
|
||||
<li key={index}>
|
||||
<Link
|
||||
to={item.link}
|
||||
className="lh-1 text-body-tertiary fw-semibold fs-9"
|
||||
>
|
||||
{item.icon && (
|
||||
<FontAwesomeIcon
|
||||
icon={item.icon}
|
||||
transform={item.transform || undefined}
|
||||
className="me-2"
|
||||
/>
|
||||
)}
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Col>
|
||||
</Row>
|
||||
<Footer className="px-0" />
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default TravelAgencyFooter;
|
||||
20
src/pages/apps/travel-agency/payment/CountdownDisplay.tsx
Normal file
20
src/pages/apps/travel-agency/payment/CountdownDisplay.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { faClock } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import React from 'react';
|
||||
|
||||
const CountdownDisplay = () => {
|
||||
return (
|
||||
<div>
|
||||
<p className="mb-2 text-info">Book before time runs out</p>
|
||||
<h3 className="mb-0 text-info fw-bold d-flex gap-2 align-items-center justify-content-sm-end">
|
||||
<FontAwesomeIcon icon={faClock} className="fs-8" />
|
||||
<span>29</span>
|
||||
<span className="fs-9 fw-normal">min</span>
|
||||
<span>50</span>
|
||||
<span className="fs-9 fw-normal">sec</span>
|
||||
</h3>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CountdownDisplay;
|
||||
82
src/pages/apps/travel-agency/payment/FlightBookingWizard.tsx
Normal file
82
src/pages/apps/travel-agency/payment/FlightBookingWizard.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import { IconProp } from '@fortawesome/fontawesome-svg-core';
|
||||
import {
|
||||
faCheck,
|
||||
faMoneyBill,
|
||||
faPlane,
|
||||
faUser
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Nav } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
interface WizardItem {
|
||||
name: string;
|
||||
icon: IconProp;
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface FlightBookingWizardProps {
|
||||
activeItem: string;
|
||||
}
|
||||
|
||||
const wizardItems: WizardItem[] = [
|
||||
{
|
||||
name: 'Flight',
|
||||
icon: faPlane,
|
||||
url: '/apps/travel-agency/flight/homepage'
|
||||
},
|
||||
{
|
||||
name: 'Booking',
|
||||
icon: faUser,
|
||||
url: '/apps/travel-agency/flight/booking'
|
||||
},
|
||||
{
|
||||
name: 'Payment',
|
||||
icon: faMoneyBill,
|
||||
url: '/apps/travel-agency/flight/payment'
|
||||
}
|
||||
];
|
||||
|
||||
const FlightBookingWizard = ({ activeItem }: FlightBookingWizardProps) => {
|
||||
const doneItems = wizardItems.filter(
|
||||
item =>
|
||||
wizardItems.indexOf(item) <
|
||||
wizardItems.findIndex(i => i.name === activeItem)
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="theme-wizard flight-booking-wizard"
|
||||
style={{ width: '18.125rem' }}
|
||||
>
|
||||
<Nav className="justify-content-between nav-wizard nav-wizard-success">
|
||||
{wizardItems.map((item, index) => {
|
||||
const isDone = doneItems.some(i => i.name === item.name);
|
||||
const isActive = activeItem === item.name;
|
||||
const stepClass = isDone ? 'done complete' : isActive ? 'active' : '';
|
||||
|
||||
return (
|
||||
<Nav.Item key={index}>
|
||||
<Nav.Link
|
||||
as={Link}
|
||||
to={item.url}
|
||||
className={`fw-semibold ${stepClass}`}
|
||||
>
|
||||
<div className="d-inline-block text-center">
|
||||
<span className="nav-item-circle-parent">
|
||||
<span className="d-block nav-item-circle">
|
||||
<FontAwesomeIcon icon={isDone ? faCheck : item.icon} />
|
||||
</span>
|
||||
</span>
|
||||
<span className="d-md-block mt-1 fs-9">{item.name}</span>
|
||||
</div>
|
||||
</Nav.Link>
|
||||
</Nav.Item>
|
||||
);
|
||||
})}
|
||||
</Nav>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlightBookingWizard;
|
||||
47
src/pages/apps/travel-agency/trip/Checkout.tsx
Normal file
47
src/pages/apps/travel-agency/trip/Checkout.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import TripSummaryCard from 'components/cards/TripSummaryCard';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { tripNavItems } from 'data/travel-agency/resizableNav';
|
||||
import { Col, Container, Form, Row } from 'react-bootstrap';
|
||||
import { selectedTrip } from 'data/travel-agency/customer/trip';
|
||||
import Button from 'components/base/Button';
|
||||
import TripCheckoutForm from 'components/forms/TripCheckoutForm';
|
||||
|
||||
const TripCheckout = () => {
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={tripNavItems} />
|
||||
<section className="py-5 pb-md-7 pb-lg-9">
|
||||
<Container fluid="medium">
|
||||
<Form onSubmit={e => e.preventDefault()}>
|
||||
<Row className="gy-5 gx-lg-0 justify-content-between">
|
||||
<Col lg={6}>
|
||||
<PageBreadcrumb
|
||||
items={defaultBreadcrumbItems}
|
||||
className="mb-3"
|
||||
/>
|
||||
<h2 className="mb-5">Check out</h2>
|
||||
<TripCheckoutForm />
|
||||
</Col>
|
||||
<Col lg={5} xl={4}>
|
||||
<div className="sticky-lg-top z-0" style={{ top: '10rem' }}>
|
||||
<TripSummaryCard selectedTrip={selectedTrip} />
|
||||
<Button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
className="w-100 mt-3"
|
||||
>
|
||||
Book now
|
||||
</Button>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</Container>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TripCheckout;
|
||||
29
src/pages/apps/travel-agency/trip/Homepage.tsx
Normal file
29
src/pages/apps/travel-agency/trip/Homepage.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import useSettingsMountEffect from 'hooks/useSettingsMountEffect';
|
||||
import NavbarHome from 'components/navbars/travel-agency/NavbarHome';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { tripNavItems } from 'data/travel-agency/resizableNav';
|
||||
import TripHomepageHeroBanner from 'components/modules/travel-agency/trip/homepage/TripHomepageHeroBanner';
|
||||
import TripHomepageTripList from 'components/modules/travel-agency/trip/homepage/TripHomepageTripList';
|
||||
import { tripHomepageItems } from 'data/travel-agency/customer/trip';
|
||||
|
||||
const TripHomepage = () => {
|
||||
useSettingsMountEffect({
|
||||
disableNavigationType: true,
|
||||
disableHorizontalNavbarAppearance: true,
|
||||
disableVerticalNavbarAppearance: true,
|
||||
disableHorizontalNavbarShape: true
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={tripNavItems} />
|
||||
<section className="container-small py-0">
|
||||
<NavbarHome currentPage="Trip" />
|
||||
</section>
|
||||
<TripHomepageHeroBanner />
|
||||
<TripHomepageTripList tripItems={tripHomepageItems} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TripHomepage;
|
||||
60
src/pages/apps/travel-agency/trip/TripDetails.tsx
Normal file
60
src/pages/apps/travel-agency/trip/TripDetails.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import useSettingsMountEffect from 'hooks/useSettingsMountEffect';
|
||||
import ResizableNavbar from 'components/navbars/travel-agency/ResizableNavbar';
|
||||
import { tripNavItems } from 'data/travel-agency/resizableNav';
|
||||
import PageBreadcrumb from 'components/common/PageBreadcrumb';
|
||||
import { defaultBreadcrumbItems } from 'data/commonData';
|
||||
import { Container, Row } from 'react-bootstrap';
|
||||
import TripDetailsOverview from 'components/modules/travel-agency/trip/trip-details/TripDetailsOverview';
|
||||
import TripDetailsGallery from 'components/modules/travel-agency/trip/trip-details/TripDetailsGallery';
|
||||
import {
|
||||
tripDetailsAlbum,
|
||||
tripHomepageItems,
|
||||
tripOverview
|
||||
} from 'data/travel-agency/customer/trip';
|
||||
import TripDetailsTab from 'components/modules/travel-agency/trip/trip-details/TripDetailsTab';
|
||||
import TripShowcaseItem from 'components/modules/travel-agency/trip/TripShowcaseItem';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const TripDetails = () => {
|
||||
useSettingsMountEffect({
|
||||
disableNavigationType: true,
|
||||
disableHorizontalNavbarAppearance: true,
|
||||
disableVerticalNavbarAppearance: true,
|
||||
disableHorizontalNavbarShape: true
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<ResizableNavbar navItems={tripNavItems} />
|
||||
<section className="pt-5 pb-5 pb-md-6 pb-lg-9">
|
||||
<Container fluid="medium">
|
||||
<PageBreadcrumb items={defaultBreadcrumbItems} className="mb-3" />
|
||||
<h2 className="mb-5">Trip Details</h2>
|
||||
<h1 className="fw-bold">
|
||||
Walk where the king walked once in Wakanda{' '}
|
||||
<span className="align-middle text-nowrap fs-8">
|
||||
<span className="text-body-quaternary">by </span>
|
||||
<Link to="#!" className="text-body-tertiary">
|
||||
Panther Travels Limited
|
||||
</Link>
|
||||
</span>
|
||||
</h1>
|
||||
<hr className="bg-secondary-lighter" />
|
||||
<TripDetailsOverview tripOverview={tripOverview} />
|
||||
<TripDetailsGallery galleryItems={tripDetailsAlbum} />
|
||||
<TripDetailsTab />
|
||||
<h2 className="mt-5 mb-3">Similar tours</h2>
|
||||
<Row className="g-3">
|
||||
{tripHomepageItems
|
||||
.slice(tripHomepageItems.length - 3)
|
||||
.map(tripItem => (
|
||||
<TripShowcaseItem showcaseItem={tripItem} key={tripItem.id} />
|
||||
))}
|
||||
</Row>
|
||||
</Container>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TripDetails;
|
||||
89
src/pages/dashboard/Crm.tsx
Normal file
89
src/pages/dashboard/Crm.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import { faCalendar, faPhoneAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import CrmStatCard from 'components/cards/CrmStatCard';
|
||||
import ContactsCreatedChart from 'components/charts/e-charts/ContactsCreatedChart';
|
||||
import LeadSources from 'components/list-items/LeadSources';
|
||||
import AdClicks from 'components/modules/crm/AdClicks';
|
||||
import ContactsBySource from 'components/modules/crm/ContactsBySource';
|
||||
import DealForecast from 'components/modules/crm/DealForecast';
|
||||
import LeadConversion from 'components/modules/crm/LeadConversion';
|
||||
import NewUsersAndLeads from 'components/modules/crm/NewUsersAndLeads';
|
||||
import RevenueTarget from 'components/modules/crm/RevenueTarget';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
|
||||
const Crm = () => {
|
||||
return (
|
||||
<>
|
||||
<Row className="mb-4 gy-3 justify-content-between">
|
||||
<Col xxl={6}>
|
||||
<h2 className="mb-2 text-body-emphasis">CRM Dashboard</h2>
|
||||
<h5 className="text-body-tertiary fw-semibold mb-4">
|
||||
Check your business growth in one place
|
||||
</h5>
|
||||
<Row className="g-3 mb-3">
|
||||
<Col sm={6} md={4} xl={3} xxl={4}>
|
||||
<CrmStatCard
|
||||
icon={faPhoneAlt}
|
||||
color="primary"
|
||||
label="Outgoing call"
|
||||
value={3}
|
||||
title="Leads Today"
|
||||
badgeLabel="+24.5%"
|
||||
badgeBg="success"
|
||||
footerText="Than yesterday"
|
||||
/>
|
||||
</Col>
|
||||
<Col sm={6} md={4} xl={3} xxl={4}>
|
||||
<CrmStatCard
|
||||
icon={faCalendar}
|
||||
color="info"
|
||||
label="Outgoing meeting"
|
||||
value={12}
|
||||
title="This Week"
|
||||
badgeLabel="+20.5%"
|
||||
badgeBg="warning"
|
||||
footerText="Than last week"
|
||||
/>
|
||||
</Col>
|
||||
<Col md={4} xl={6} xxl={4}>
|
||||
<div className="border-bottom">
|
||||
<h5 className="pb-4 border-bottom">Top 5 Lead Sources</h5>
|
||||
<LeadSources />
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xxl={6} className="mb-6">
|
||||
<h3>Contacts Created</h3>
|
||||
<p className="text-body-tertiary mb-1">
|
||||
Payment received across all channels
|
||||
</p>
|
||||
<ContactsCreatedChart style={{ height: 270, width: '100%' }} />
|
||||
</Col>
|
||||
<Col xs={12} xxl={6} className="mb-3 mb-sm-0">
|
||||
<ContactsBySource />
|
||||
</Col>
|
||||
<Col xs={12} xxl={6} className="mb-8">
|
||||
<NewUsersAndLeads />
|
||||
</Col>
|
||||
<Col xs={12} xxl={6}>
|
||||
<AdClicks />
|
||||
</Col>
|
||||
<Col xs={12} xxl={6} className="mb-6 gy-0 gy-xxl-3">
|
||||
<DealForecast />
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="mx-lg-n4">
|
||||
<Row className="g-3 mb-9 mt-n7">
|
||||
<Col xs={12} xl={5}>
|
||||
<LeadConversion />
|
||||
</Col>
|
||||
<Col xs={12} xl={7}>
|
||||
<RevenueTarget />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Crm;
|
||||
84
src/pages/dashboard/ProjectManagement.tsx
Normal file
84
src/pages/dashboard/ProjectManagement.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import DatePicker from 'components/base/DatePicker';
|
||||
import EarlyBirdCard from 'components/cards/EarlyBirdCard';
|
||||
import ZeroRoadMap from 'components/modules/project-management/dashboard/ZeroRoadMap';
|
||||
import IssuesDiscovered from 'components/modules/project-management/dashboard/IssuesDiscovered';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import TodoList from 'components/modules/project-management/todo-list/TodoList';
|
||||
import { stats } from 'data/project-management/stats';
|
||||
import Stat from 'components/modules/project-management/dashboard/Stat';
|
||||
import ProjectElevenProgress from 'components/modules/project-management/dashboard/ProjectElevenProgress';
|
||||
import ProjectDashboard from 'components/modules/project-management/dashboard/ProjectDashboard';
|
||||
import ProjectActivityCard from 'components/cards/ProjectActivityCard';
|
||||
|
||||
const ProjectManagement = () => {
|
||||
return (
|
||||
<>
|
||||
<Row className="gy-3 mb-6 justify-content-between">
|
||||
<Col md={9} xs="auto">
|
||||
<h2 className="mb-2 text-body-emphasis">Projects Dashboard</h2>
|
||||
<h5 className="text-body-tertiary fw-semibold">
|
||||
Here’s what’s going on at your business right now
|
||||
</h5>
|
||||
</Col>
|
||||
<Col md={3} xs="auto">
|
||||
<DatePicker
|
||||
options={{
|
||||
defaultDate: 'May 1, 2023'
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="mb-3 gy-6">
|
||||
<Col xs={12} xxl={2}>
|
||||
<Row className="align-items-center g-3 g-xxl-0 h-100 align-content-between">
|
||||
{stats.map(stat => (
|
||||
<Col
|
||||
xs={12}
|
||||
sm={6}
|
||||
md={3}
|
||||
lg={6}
|
||||
xl={3}
|
||||
xxl={12}
|
||||
key={stat.title}
|
||||
>
|
||||
<Stat stat={stat} key={stat.title} />
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xs={12} xl={6} xxl={5}>
|
||||
<ZeroRoadMap />
|
||||
</Col>
|
||||
<Col xs={12} xl={6} xxl={5}>
|
||||
<EarlyBirdCard />
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis pt-7 pb-3 border-y mb-3">
|
||||
<Row>
|
||||
<Col xs={12} xl={7} xxl={6}>
|
||||
<IssuesDiscovered />
|
||||
</Col>
|
||||
<Col xs={12} xl={5} xxl={6}>
|
||||
<ProjectElevenProgress />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<div className="mx-lg-n4 mb-3">
|
||||
<Row className="g-3">
|
||||
<Col xs={12} xl={6} xxl={7}>
|
||||
<TodoList />
|
||||
</Col>
|
||||
<Col xs={12} xl={6} xxl={5}>
|
||||
<ProjectActivityCard />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis pt-6 border-top">
|
||||
<ProjectDashboard />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectManagement;
|
||||
76
src/pages/dashboard/TravelAgency.tsx
Normal file
76
src/pages/dashboard/TravelAgency.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import { faCalendarDays } from '@fortawesome/free-regular-svg-icons';
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { TravelStatistics } from 'components/modules/travel-agency/dashboard/TravelStatistics';
|
||||
import { FinancialActivities } from 'components/modules/travel-agency/dashboard/FinancialActivities';
|
||||
import { HolidaysCard } from 'components/cards/HolidaysCard';
|
||||
import { IntegrationsCard } from 'components/cta/IntegrationsCard';
|
||||
import Bookings from 'components/modules/travel-agency/dashboard/Bookings';
|
||||
import Flights from 'components/modules/travel-agency/dashboard/Flights';
|
||||
import { VisitorsCard } from 'components/cards/VisitorsCard';
|
||||
import GrossProfitCard from 'components/cards/GrossProfitCard';
|
||||
|
||||
const TravelAgency = () => {
|
||||
return (
|
||||
<>
|
||||
<Row className="mb-4 mb-xl-6 mb-xxl-4 gy-3 justify-content-between">
|
||||
<Col xs="auto">
|
||||
<h2> Travel Agency </h2>
|
||||
</Col>
|
||||
<Col xs="auto">
|
||||
<div className="d-flex gap-3">
|
||||
<Link to="#!" className="btn btn-phoenix-primary">
|
||||
<FontAwesomeIcon icon={faPlus} className="me-2" />
|
||||
New Package
|
||||
</Link>
|
||||
<Link to="#!" className="btn btn-primary px-4 px-sm-11">
|
||||
<FontAwesomeIcon icon={faCalendarDays} className="me-2" />
|
||||
Book Now
|
||||
</Link>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row className="gx-3">
|
||||
<Col xxl={7}>
|
||||
<Row className="gx-7 pe-xxl-3">
|
||||
<Col xs={12} xl={5} xxl={12}>
|
||||
<TravelStatistics />
|
||||
</Col>
|
||||
<Col xs={12} xl={7} xxl={12}>
|
||||
<FinancialActivities />
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xxl={5}>
|
||||
<Row className="g-3">
|
||||
<Col xs={12} lg={6} xxl={12}>
|
||||
<VisitorsCard />
|
||||
</Col>
|
||||
<Col xs={12} lg={6} xxl={12}>
|
||||
<HolidaysCard />
|
||||
</Col>
|
||||
<Col xs={12}>
|
||||
<IntegrationsCard />
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="g-3 mb-5">
|
||||
<Col xl={5} xxl={7}>
|
||||
<GrossProfitCard />
|
||||
</Col>
|
||||
<Col xl={7} xxl={5}>
|
||||
<Bookings />
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 pb-9 bg-body-emphasis border-top">
|
||||
<Flights />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TravelAgency;
|
||||
78
src/pages/dashboard/ecommerce/index.tsx
Normal file
78
src/pages/dashboard/ecommerce/index.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import EcomTotalOrdersCard from 'components/cards/EcomTotalOrdersCard';
|
||||
import EcomNewCustomersCard from 'components/cards/EcomNewCustomersCard';
|
||||
import EcomTopCouponsCard from 'components/cards/EcomTopCouponsCard';
|
||||
import EcomPayingVsNonPayingCard from 'components/cards/EcomPayingVsNonPayingCard';
|
||||
import EcomLatestReviewsTable from 'components/tables/EcomLatestReviewsTable';
|
||||
import EcomTopRegionsMap from 'components/leaflet-maps/EcomTopRegionsMap';
|
||||
import EcomStats from 'components/stats/EcomStats';
|
||||
import { mapMarkerPoints } from 'data/mapMarkerPoints';
|
||||
import EcomProjectionVsActual from 'components/modules/e-commerce/dashboard/EcomProjectionVsActual';
|
||||
import EcomReturningCustomerRate from 'components/modules/e-commerce/dashboard/EcomReturningCustomerRate';
|
||||
import EcomTotalSells from 'components/modules/e-commerce/dashboard/EcomTotalSells';
|
||||
import EcomTopRegions from 'components/modules/e-commerce/dashboard/EcomTopRegions';
|
||||
|
||||
const Ecommerce = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="pb-5">
|
||||
<Row className="g-4">
|
||||
<Col xs={12} xxl={6}>
|
||||
<div className="mb-8">
|
||||
<h2 className="mb-2">Ecommerce Dashboard</h2>
|
||||
<h5 className="text-body-tertiary fw-semibold">
|
||||
Here’s what’s going on at your business right now
|
||||
</h5>
|
||||
</div>
|
||||
<EcomStats />
|
||||
<hr className="bg-body-secondary mb-6 mt-4" />
|
||||
<EcomTotalSells />
|
||||
</Col>
|
||||
<Col xs={12} xxl={6}>
|
||||
<Row className="g-3">
|
||||
<Col xs={12} md={6}>
|
||||
<EcomTotalOrdersCard />
|
||||
</Col>
|
||||
<Col xs={12} md={6}>
|
||||
<EcomNewCustomersCard />
|
||||
</Col>
|
||||
<Col xs={12} md={6}>
|
||||
<EcomTopCouponsCard />
|
||||
</Col>
|
||||
<Col xs={12} md={6}>
|
||||
<EcomPayingVsNonPayingCard />
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis pt-7 border-y">
|
||||
<EcomLatestReviewsTable />
|
||||
</div>
|
||||
<Row className="gx-6">
|
||||
<Col xs={12} xl={6}>
|
||||
<EcomTopRegions />
|
||||
</Col>
|
||||
<Col xs={12} xl={6}>
|
||||
<div className="mx-n4 mx-lg-n6 ms-xl-0 h-100">
|
||||
<div className="h-100 w-100" style={{ minHeight: 300 }}>
|
||||
<EcomTopRegionsMap data={mapMarkerPoints} />
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="mx-n4 px-4 mx-lg-n6 px-lg-6 bg-body-emphasis pt-6 pb-9 border-top">
|
||||
<Row className="g-6">
|
||||
<Col xs={12} xl={6}>
|
||||
<EcomProjectionVsActual />
|
||||
</Col>
|
||||
<Col xs={12} xl={6}>
|
||||
<EcomReturningCustomerRate />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Ecommerce;
|
||||
98
src/pages/documentation/ChangeLog.tsx
Normal file
98
src/pages/documentation/ChangeLog.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import {
|
||||
faChevronRight,
|
||||
faCircleInfo
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Button from 'components/base/Button';
|
||||
import PhoenixDocCard from 'components/base/PhoenixDocCard';
|
||||
import changelogs from 'data/changelog';
|
||||
import { Alert } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const ChangeLog = () => {
|
||||
return (
|
||||
<div>
|
||||
<h2 className="mb-4 lh-sm">Changelog</h2>
|
||||
|
||||
{changelogs.map(changelog => (
|
||||
<PhoenixDocCard className="mb-4" key={changelog.title}>
|
||||
<PhoenixDocCard.Header noPreview>
|
||||
<div className="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5 className="mb-2">
|
||||
<code className="fw-bold fs-7">v{changelog.version}</code> -{' '}
|
||||
{changelog.title}
|
||||
</h5>
|
||||
<p className="mb-0">{changelog.publishDate}</p>
|
||||
</div>
|
||||
<Button
|
||||
as={Link}
|
||||
variant="link"
|
||||
to={`/migrations/#${changelog.version}`}
|
||||
endIcon={
|
||||
<FontAwesomeIcon icon={faChevronRight} className="fs-10" />
|
||||
}
|
||||
>
|
||||
See migration
|
||||
</Button>
|
||||
</div>
|
||||
</PhoenixDocCard.Header>
|
||||
<PhoenixDocCard.Body>
|
||||
{changelog.alertText && (
|
||||
<Alert
|
||||
variant={'subtle-warning'}
|
||||
className="d-flex align-items-center"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={faCircleInfo}
|
||||
className="text-warning fs-5 me-3"
|
||||
/>
|
||||
{changelog.alertText}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{/* New */}
|
||||
<h6 className="d-inline-block">New</h6>
|
||||
<ul>
|
||||
{changelog.logs.new.map(file => (
|
||||
<li dangerouslySetInnerHTML={{ __html: file }} key={file} />
|
||||
))}
|
||||
</ul>
|
||||
{/* Update */}
|
||||
{changelog.logs.update && (
|
||||
<>
|
||||
<h6 className="d-inline-block">Update</h6>
|
||||
<ul>
|
||||
{changelog.logs.update.map(file => (
|
||||
<li dangerouslySetInnerHTML={{ __html: file }} key={file} />
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
{/* Fix */}
|
||||
<h6 className="d-inline-block">Fix</h6>
|
||||
<ul>
|
||||
{changelog.logs.fix.map(file => (
|
||||
<li dangerouslySetInnerHTML={{ __html: file }} key={file} />
|
||||
))}
|
||||
</ul>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
))}
|
||||
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header noPreview>
|
||||
<h5 className="mb-2">
|
||||
<code className="fw-bold fs-7">v1.0.0</code> - Initial Release
|
||||
</h5>
|
||||
<p className="mb-0">11 Sep, 2023</p>
|
||||
</PhoenixDocCard.Header>
|
||||
<PhoenixDocCard.Body>
|
||||
<p className="mb-0">Nothing to see here.</p>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChangeLog;
|
||||
33
src/pages/documentation/DesignFile.tsx
Normal file
33
src/pages/documentation/DesignFile.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import PhoenixDocCard from 'components/base/PhoenixDocCard';
|
||||
import React from 'react';
|
||||
|
||||
const DesignFile = () => {
|
||||
return (
|
||||
<div>
|
||||
<h2 className="mb-4 lh-sm">Design</h2>
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header title="Figma file" noPreview />
|
||||
<PhoenixDocCard.Body>
|
||||
<h5 className="mb-2">To play with the design:</h5>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://www.figma.com/" target="_blank" rel="noreferrer">
|
||||
Download Figma
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
Open the Figma link from the <code>README.md</code>
|
||||
</li>
|
||||
<li>
|
||||
This file is <code>"read-only". </code>So, to customize the design
|
||||
on your own, you have to duplicate the Figma file and start the
|
||||
editing process on the copied file.
|
||||
</li>
|
||||
</ul>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DesignFile;
|
||||
116
src/pages/documentation/GettingStarted.tsx
Normal file
116
src/pages/documentation/GettingStarted.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
import PhoenixDocCard from 'components/base/PhoenixDocCard';
|
||||
import DocPageHeader from 'components/docs/DocPageHeader';
|
||||
import PhoenixLiveEditor from 'components/docs/PhoenixLiveEditor';
|
||||
import DocPagesLayout from 'layouts/DocPagesLayout';
|
||||
|
||||
const serveCode = `
|
||||
npm install -g serve
|
||||
serve -s build
|
||||
`;
|
||||
|
||||
const GettingStarted = () => {
|
||||
return (
|
||||
<div>
|
||||
<DocPageHeader className="mb-4" title="Getting Started">
|
||||
<p className="mb-0">
|
||||
Welcome to the ReactJS version of the{' '}
|
||||
<a
|
||||
href="https://themes.getbootstrap.com/product/phoenix-admin-dashboard-webapp-template/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
original {process.env.REACT_APP_TITLE} theme{' '}
|
||||
</a>
|
||||
. This doc will guide you to understand how{' '}
|
||||
<strong>{process.env.REACT_APP_TITLE}-React</strong> theme is
|
||||
organized, basics of how to customize, and how to compile from the
|
||||
source code if you want.
|
||||
</p>
|
||||
</DocPageHeader>
|
||||
<DocPagesLayout>
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header
|
||||
title="Running in Local environment"
|
||||
noPreview
|
||||
/>
|
||||
<PhoenixDocCard.Body>
|
||||
<p>
|
||||
This project is scaffolded using{' '}
|
||||
<a
|
||||
href="https://create-react-app.dev"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Create React App
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<ol className="mb-0 ps-3">
|
||||
<li>
|
||||
Install{' '}
|
||||
<a
|
||||
href="https://nodejs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Node.js
|
||||
</a>{' '}
|
||||
if you do not already have it installed on your machine.
|
||||
</li>
|
||||
<li>
|
||||
Open the “{process.env.REACT_APP_NAME}-react-v
|
||||
{process.env.REACT_APP_VERSION}” directory with your cmd or
|
||||
terminal
|
||||
</li>
|
||||
<li>
|
||||
Run <code>npm i</code>
|
||||
<br />
|
||||
This command will download all the necessary dependencies for{' '}
|
||||
{process.env.REACT_APP_NAME} in the <code>node_modules</code>{' '}
|
||||
directory.
|
||||
</li>
|
||||
<li>
|
||||
Run <code>npm start</code>. A local web server will start at{' '}
|
||||
<code>http://localhost:3000</code>
|
||||
</li>
|
||||
</ol>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header
|
||||
title="Creating a Production Build"
|
||||
noPreview
|
||||
/>
|
||||
<PhoenixDocCard.Body>
|
||||
<p>
|
||||
After you done your customization, when you are ready to build,
|
||||
Edit <code>homapage</code> in your <code>package.json</code> file
|
||||
to change asset files relative paths. For more information visit{' '}
|
||||
<a
|
||||
href="https://create-react-app.dev/docs/deployment/#building-for-relative-paths"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Create React App Doc.
|
||||
</a>{' '}
|
||||
Then Run <code>npm run build</code> command in your project
|
||||
directory to make the Production build.
|
||||
</p>
|
||||
<p>
|
||||
This will create an optimized production build by compililing,
|
||||
merging and minifying all the source files as necessary and will
|
||||
put them in the <code>build/</code> folder.
|
||||
</p>
|
||||
<p>
|
||||
To run the production build locally run the following commands:
|
||||
</p>
|
||||
<PhoenixLiveEditor code={serveCode} />
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
</DocPagesLayout>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GettingStarted;
|
||||
87
src/pages/documentation/Migrations.tsx
Normal file
87
src/pages/documentation/Migrations.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import PhoenixDocCard from 'components/base/PhoenixDocCard';
|
||||
import migrations from 'data/migrations';
|
||||
import { Alert, Card } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const Migrations = () => {
|
||||
return (
|
||||
<div>
|
||||
<h2 className="mb-4 lh-sm">Migrations</h2>
|
||||
|
||||
<Card className="mb-4">
|
||||
<Card.Body>
|
||||
<Alert variant="subtle-warning" className="mb-0">
|
||||
<div className="d-flex">
|
||||
<FontAwesomeIcon icon={faExclamationTriangle} className="fs-5" />
|
||||
<div className="ms-3 flex-1">
|
||||
<h4 className="alert-heading">Before you update!</h4>
|
||||
Backup your files and read the changelog before updating{' '}
|
||||
{process.env.REACT_APP_TITLE}-React on your project. If you come
|
||||
across with any problems with {process.env.REACT_APP_TITLE}
|
||||
-React template during the update, feel free to contact us at{' '}
|
||||
<a href="mailto:support@themewagon.com">
|
||||
support@themewagon.com
|
||||
</a>
|
||||
.
|
||||
</div>
|
||||
</div>
|
||||
</Alert>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
|
||||
{migrations.map(migration => (
|
||||
<PhoenixDocCard className="mb-4" key={migration.from}>
|
||||
<PhoenixDocCard.Header noPreview>
|
||||
<div className="d-flex align-items-center">
|
||||
<p className="text-body text-nowrap mb-0">
|
||||
<code className="fs-7 opacity-50">{migration.from}</code>
|
||||
<span className="mx-3">to</span>
|
||||
<code className="fs-7">{migration.to}</code>
|
||||
</p>
|
||||
<Link
|
||||
to={`#${migration.to}`}
|
||||
className="opacity-0 hover-show fw-bold ps-2"
|
||||
>
|
||||
#
|
||||
</Link>
|
||||
</div>
|
||||
</PhoenixDocCard.Header>
|
||||
<PhoenixDocCard.Body>
|
||||
<ul className="bullet-inside ps-0">
|
||||
<li>
|
||||
<h6 className="d-inline-block">Add</h6>
|
||||
<ul>
|
||||
{migration.new.map(file => (
|
||||
<li key={file}>{file}</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h6 className="d-inline-block">Modify</h6>
|
||||
<ul>
|
||||
{migration.update.map(file => (
|
||||
<li key={file}>{file}</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
{migration.delete && (
|
||||
<li>
|
||||
<h6 className="d-inline-block">Remove</h6>
|
||||
<ul>
|
||||
{migration.delete.map(file => (
|
||||
<li key={file}>{file}</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Migrations;
|
||||
295
src/pages/documentation/customization/Color.tsx
Normal file
295
src/pages/documentation/customization/Color.tsx
Normal file
@@ -0,0 +1,295 @@
|
||||
import PhoenixDocCard from 'components/base/PhoenixDocCard';
|
||||
import DocPageHeader from 'components/docs/DocPageHeader';
|
||||
import React from 'react';
|
||||
import { Table } from 'react-bootstrap';
|
||||
|
||||
const BodyColorDemo = () => {
|
||||
return (
|
||||
<>
|
||||
<tr>
|
||||
<td rowSpan={2}>
|
||||
<strong>body</strong>
|
||||
</td>
|
||||
<td className="ps-0">
|
||||
<div
|
||||
className="p-5 rounded-2"
|
||||
style={{
|
||||
backgroundColor: 'var(--phoenix-body-color)'
|
||||
}}
|
||||
></div>
|
||||
</td>
|
||||
<td>
|
||||
<code>--phoenix-body-color</code>
|
||||
<br />
|
||||
<code>--phoenix-body-color-rgb</code>
|
||||
</td>
|
||||
<td>
|
||||
<code>text-body</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div
|
||||
className="p-5 rounded-2"
|
||||
style={{
|
||||
backgroundColor: 'var(--phoenix-body-bg)'
|
||||
}}
|
||||
></div>
|
||||
</td>
|
||||
<td>
|
||||
<code>--phoenix-bg-color</code>
|
||||
<br />
|
||||
<code>--phoenix-body-bg-rgb</code>
|
||||
</td>
|
||||
<td>
|
||||
<code>bg-body</code>
|
||||
</td>
|
||||
</tr>
|
||||
</>
|
||||
);
|
||||
};
|
||||
const ColorDemo = ({ color }: { color: string }) => {
|
||||
return (
|
||||
<>
|
||||
<tr>
|
||||
<td rowSpan={2}>
|
||||
<strong className="text-capitalize">{color}</strong>
|
||||
</td>
|
||||
<td className="ps-0">
|
||||
<div
|
||||
className="p-5 rounded-2"
|
||||
style={{
|
||||
backgroundColor: `var(--phoenix-${color}-color)`
|
||||
}}
|
||||
></div>
|
||||
</td>
|
||||
<td>
|
||||
<code>--phoenix-{color}-color</code>
|
||||
<br />
|
||||
<code>--phoenix-{color}-color-rgb</code>
|
||||
</td>
|
||||
<td>
|
||||
{color === 'body-highlight' ? (
|
||||
<code>text-{color}</code>
|
||||
) : (
|
||||
<code>text-body-{color}</code>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div
|
||||
className="p-5 rounded-2"
|
||||
style={{
|
||||
backgroundColor: `var(--phoenix-${color}-color)`
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<code>--phoenix-{color}-bg</code>
|
||||
<br />
|
||||
<code>--phoenix-{color}-bg-rgb</code>
|
||||
</td>
|
||||
<td>
|
||||
{color === 'body-highlight' ? (
|
||||
<code>bg-{color}</code>
|
||||
) : (
|
||||
<code>bg-body-{color}</code>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
</>
|
||||
);
|
||||
};
|
||||
const ColorShadesDemo = ({ color }: { color: string }) => {
|
||||
const variants = ['subtle', 'lighter', 'light', 'dark', 'darker', 'emphasis'];
|
||||
return (
|
||||
<>
|
||||
<tr>
|
||||
<td rowSpan={7}>
|
||||
<strong className="text-capitalize">{color}</strong>
|
||||
</td>
|
||||
<td className="ps-0">
|
||||
<div className={`p-5 rounded-2 bg-${color}`}></div>
|
||||
</td>
|
||||
<td>
|
||||
<code>--phoenix-{color}</code>
|
||||
<br />
|
||||
<code>--phoenix-{color}-rgb</code>
|
||||
</td>
|
||||
<td>
|
||||
<code>text-{color}</code>
|
||||
<br />
|
||||
<code>bg-{color}</code>
|
||||
</td>
|
||||
</tr>
|
||||
{variants.map((variant, index) => {
|
||||
return (
|
||||
<>
|
||||
{variant === 'subtle' ? (
|
||||
<tr key={index}>
|
||||
<td className="ps-0">
|
||||
<div className={`p-5 rounded-2 bg-${color}-${variant}`}></div>
|
||||
</td>
|
||||
<td>
|
||||
<code>
|
||||
--phoenix-{color}-bg-{variant}
|
||||
</code>
|
||||
</td>
|
||||
<td>
|
||||
<code>
|
||||
text-{color}-{variant}
|
||||
</code>
|
||||
<br />
|
||||
<code>
|
||||
bg-{color}-{variant}
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
) : variant === 'emphasis' ? (
|
||||
<tr key={index}>
|
||||
<td className="ps-0">
|
||||
<div className={`p-5 rounded-2 bg-${color}-${variant}`}></div>
|
||||
</td>
|
||||
<td>
|
||||
<code>
|
||||
--phoenix-{color}-{variant}
|
||||
</code>
|
||||
</td>
|
||||
<td>
|
||||
<code>
|
||||
text-{color}-{variant}
|
||||
</code>
|
||||
<br />
|
||||
<code>
|
||||
bg-{color}-{variant}
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
<tr key={index}>
|
||||
<td className="ps-0">
|
||||
<div className={`p-5 rounded-2 bg-${color}-${variant}`}></div>
|
||||
</td>
|
||||
<td>
|
||||
<code>
|
||||
--phoenix-{color}-{variant}
|
||||
</code>
|
||||
<br />
|
||||
<code>
|
||||
--phoenix-{color}-{variant}-rgb
|
||||
</code>
|
||||
</td>
|
||||
<td>
|
||||
<code>
|
||||
text-{color}-{variant}
|
||||
</code>
|
||||
<br />
|
||||
<code>
|
||||
bg-{color}-{variant}
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
{/* <tr key={index}>
|
||||
<td className="ps-0">
|
||||
<div className={`p-5 rounded-2 bg-${color}-${variant}`}></div>
|
||||
</td>
|
||||
<td>
|
||||
<code>
|
||||
--phoenix-{color}-{variant}
|
||||
</code>
|
||||
<br />
|
||||
<code>
|
||||
--phoenix-{color}-{variant}-rgb
|
||||
</code>
|
||||
</td>
|
||||
<td>
|
||||
<code>
|
||||
text-{color}-{variant}
|
||||
</code>
|
||||
<br />
|
||||
<code>
|
||||
bg-{color}-{variant}
|
||||
</code>
|
||||
</td>
|
||||
</tr> */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
const Color = () => {
|
||||
return (
|
||||
<div>
|
||||
<DocPageHeader
|
||||
title="Color"
|
||||
description="Phoenix is supported by an extensive color system that themes our styles and components. This enables more comprehensive customization and extension for any project."
|
||||
/>
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header title="Config Context" noPreview>
|
||||
<p className="text-body-tertiary mb-0">
|
||||
Phoenix comes with lots of colors and variants. We added
|
||||
<code> quaternary </code>
|
||||
and <code> body-highlight </code> colors besides
|
||||
<code> secondary </code> and
|
||||
<code> tertiary </code> colors and also theme colors shades.
|
||||
</p>
|
||||
</PhoenixDocCard.Header>
|
||||
<PhoenixDocCard.Body>
|
||||
<Table responsive className="table-swatches">
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
className="ps-0"
|
||||
style={{ width: '20%', minWidth: '100px' }}
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
className="ps-0"
|
||||
style={{ width: '20%', minWidth: '130px' }}
|
||||
>
|
||||
Swatch
|
||||
</th>
|
||||
<th
|
||||
className="ps-0"
|
||||
style={{ width: '40%', minWidth: '330px' }}
|
||||
>
|
||||
CSS variables
|
||||
</th>
|
||||
<th
|
||||
className="ps-0"
|
||||
style={{ width: '20%', minWidth: '230px' }}
|
||||
>
|
||||
Class
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<BodyColorDemo />
|
||||
{['secondary', 'tertiary', 'quaternary', 'body-highlight'].map(
|
||||
(color, index) => (
|
||||
<ColorDemo color={color} key={index} />
|
||||
)
|
||||
)}
|
||||
{[
|
||||
'primary',
|
||||
'secondary',
|
||||
'success',
|
||||
'danger',
|
||||
'warning',
|
||||
'info'
|
||||
].map((color, index) => (
|
||||
<ColorShadesDemo color={color} key={index} />
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Color;
|
||||
217
src/pages/documentation/customization/Configuration.tsx
Normal file
217
src/pages/documentation/customization/Configuration.tsx
Normal file
@@ -0,0 +1,217 @@
|
||||
import PhoenixDocCard from 'components/base/PhoenixDocCard';
|
||||
import DocPageHeader from 'components/docs/DocPageHeader';
|
||||
import PhoenixLiveEditor from 'components/docs/PhoenixLiveEditor';
|
||||
|
||||
const exampleCode = `
|
||||
export const initialConfig = {
|
||||
isNavbarVerticalCollapsed: false,
|
||||
openNavbarVertical: false, // for responsive
|
||||
theme: 'light',
|
||||
navbarTopAppearance: 'default',
|
||||
navbarVerticalAppearance: 'default',
|
||||
navbarPosition: 'vertical',
|
||||
navbarTopShape: 'default',
|
||||
isRTL: false,
|
||||
isChatWidgetVisible: true
|
||||
};`;
|
||||
|
||||
const contextCode = `
|
||||
import { useAppContext } from 'providers/AppProvider';
|
||||
|
||||
const { config, setConfig } = useAppContext();
|
||||
|
||||
// update any config value
|
||||
setConfig({
|
||||
theme: 'dark',
|
||||
navbarTopShape:'slim'
|
||||
// any config value
|
||||
});
|
||||
`;
|
||||
|
||||
const Configuration = () => {
|
||||
return (
|
||||
<div>
|
||||
<DocPageHeader
|
||||
title="Setting up configuration"
|
||||
description="Phoenix-React has a global configuration system. You can change the theme settings with a single global javascript object."
|
||||
/>
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header title="Settings configuration" noPreview />
|
||||
<PhoenixDocCard.Body>
|
||||
<p>
|
||||
Control side panel settings from one place. Go to{' '}
|
||||
<code>src/config.ts</code> file and set your setting configuration.
|
||||
If any config value is already saved in local storage and you want
|
||||
to change the default config, please clear the local storage first.
|
||||
</p>
|
||||
<PhoenixLiveEditor code={exampleCode} />
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header title="Available Options" noPreview />
|
||||
<PhoenixDocCard.Body>
|
||||
<table className="fs--1 mb-0 table table-bordered">
|
||||
<thead className="bg-body-secondary text-body">
|
||||
<tr>
|
||||
<th className="white-space-nowrap" style={{ width: '20%' }}>
|
||||
Option
|
||||
</th>
|
||||
<th className="white-space-nowrap" style={{ width: '20%' }}>
|
||||
Type
|
||||
</th>
|
||||
<th className="white-space-nowrap" style={{ width: '20%' }}>
|
||||
Defaults
|
||||
</th>
|
||||
<th className="white-space-nowrap">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="white-space-nowrap">
|
||||
isNavbarVerticalCollapsed
|
||||
</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code>Boolean</code>
|
||||
</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code>false</code>
|
||||
</td>
|
||||
<td>
|
||||
Set <code>true</code> to make the vertical navbar stay
|
||||
collapsed when the page loads.{' '}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="white-space-nowrap">openNavbarVertical</td>
|
||||
<td>
|
||||
<code>Boolean</code>
|
||||
</td>
|
||||
<td>
|
||||
<code>false</code>
|
||||
</td>
|
||||
<td>
|
||||
This option is for showing up the{' '}
|
||||
<code> vertical navbar </code> menus in small screens{' '}
|
||||
<code>(sm to lg)</code>.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="white-space-nowrap">theme</td>
|
||||
<td>
|
||||
<code> light | dark</code>
|
||||
</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code>light</code>
|
||||
</td>
|
||||
<td>
|
||||
This option is to set the <code> theme </code> mode. Set
|
||||
<code> light </code> or <code> dark </code> to make the
|
||||
default theme mode.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="white-space-nowrap">navbarTopAppearance</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code> default | darker </code>
|
||||
</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code> default </code>
|
||||
</td>
|
||||
<td>
|
||||
This option is for setting up the{' '}
|
||||
<code> Navbar Top Appearance</code>. To make a darker top
|
||||
navbar (lighter in dark mode) set the value to{' '}
|
||||
<code> darker </code>.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="white-space-nowrap">navbarVerticalAppearance</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code> default | darker </code>
|
||||
</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code> default </code>
|
||||
</td>
|
||||
<td>
|
||||
This option is for setting up the{' '}
|
||||
<code> Navbar Vertical Appearance</code>. To make a darker
|
||||
vertical navbar (lighter in dark mode) set the value to{' '}
|
||||
<code> darker </code>.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="white-space-nowrap">navbarPosition</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code>horizontal | vertical | combo</code>
|
||||
</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code>vertical</code>
|
||||
</td>
|
||||
<td>For setting the navbar position.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td className="white-space-nowrap">navbarTopShape</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code>default | slim</code>
|
||||
</td>
|
||||
<td className="white-space-nowrap">
|
||||
<code>default</code>
|
||||
</td>
|
||||
<td>For setting the top navbar shape.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="white-space-nowrap">isRTL</td>
|
||||
<td>
|
||||
<code>Boolean</code>
|
||||
</td>
|
||||
<td>
|
||||
<code>false</code>
|
||||
</td>
|
||||
<td>
|
||||
Set <code>true</code> to make the whole layout RTL (Right to
|
||||
Left). Recommended for languages such as Arabic, Hebrew and
|
||||
others.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="white-space-nowrap">isChatWidgetVisible</td>
|
||||
<td>
|
||||
<code>Boolean</code>
|
||||
</td>
|
||||
<td>
|
||||
<code>true</code>
|
||||
</td>
|
||||
<td>
|
||||
Set <code>false</code> to hide the chat widget when the page
|
||||
loads.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header title="Config Context" noPreview />
|
||||
<PhoenixDocCard.Body>
|
||||
<p>
|
||||
{process.env.REACT_APP_TITLE} React uses{' '}
|
||||
<a href="https://legacy.reactjs.org/docs/context.html#reactcreatecontext">
|
||||
React context
|
||||
</a>{' '}
|
||||
to manage config state. To access and update any config value in
|
||||
your component use our custom hook <code>useAppContext</code>.
|
||||
</p>
|
||||
<PhoenixLiveEditor code={contextCode} />
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Configuration;
|
||||
233
src/pages/documentation/customization/DarkMode.tsx
Normal file
233
src/pages/documentation/customization/DarkMode.tsx
Normal file
@@ -0,0 +1,233 @@
|
||||
import PhoenixDocCard from 'components/base/PhoenixDocCard';
|
||||
import DocPageHeader from 'components/docs/DocPageHeader';
|
||||
import DocPagesLayout from 'layouts/DocPagesLayout';
|
||||
import { useAppContext } from 'providers/AppProvider';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import FeatherIcon from 'feather-icons-react';
|
||||
import ThemeToggler from 'components/common/ThemeToggler';
|
||||
import PhoenixDocProvider from 'providers/PhoenixDocProvider';
|
||||
import ThemeDropdown from 'components/docs/ThemeDropdown';
|
||||
|
||||
const darkModeExampleCode = `
|
||||
import { useAppContext } from 'providers/AppProvider';
|
||||
import FeatherIcon from 'feather-icons-react';
|
||||
|
||||
const DarkModeExample = () => {
|
||||
const {
|
||||
config: { theme },
|
||||
setConfig
|
||||
} = useAppContext(); // import AppContext from 'src/context/Context.js'
|
||||
|
||||
return (
|
||||
<Row className='g-3'>
|
||||
<Col>
|
||||
<h5 className="fs-0 mb-2">Checkbox </h5>
|
||||
<Form.Check
|
||||
type="checkbox"
|
||||
id="themeToggleCheckBox"
|
||||
label="Dark mode"
|
||||
onChange={e => setConfig({ theme: e.target.checked ? 'dark' : 'light' })}
|
||||
checked={theme === 'dark'}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col>
|
||||
<h5 className="fs-0 mb-2">Switch Input</h5>
|
||||
<Form.Check
|
||||
type="switch"
|
||||
id="themeToggleSwitch"
|
||||
label="Dark mode"
|
||||
onChange={e => setConfig({ theme: e.target.checked ? 'dark' : 'light' })}
|
||||
checked={theme === 'dark'}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col>
|
||||
<h5 className="fs-0 mb-2">Custom Icon</h5>
|
||||
<ThemeToggler />
|
||||
</Col>
|
||||
|
||||
<Col>
|
||||
<h5 className="fs-0 mb-2">Dropdown</h5>
|
||||
<ThemeDropdown />
|
||||
</Col>
|
||||
<Col-12>
|
||||
<h5 className="fs-0 mb-2">Radio Button</h5>
|
||||
<Form.Group className="d-flex">
|
||||
<Form.Check
|
||||
inline
|
||||
type="radio"
|
||||
id="lightRadioButton"
|
||||
label="Light"
|
||||
name="themeToggleRadio"
|
||||
checked={theme === 'light'}
|
||||
onChange={() => setConfig({ theme: 'light' })}
|
||||
/>
|
||||
<Form.Check
|
||||
inline
|
||||
type="radio"
|
||||
id="darkRadioButton"
|
||||
label="Dark"
|
||||
name="themeToggleRadio"
|
||||
checked={theme === 'dark'}
|
||||
onChange={() => setConfig({ theme: 'dark' })}
|
||||
/>
|
||||
<Form.Check
|
||||
inline
|
||||
type="radio"
|
||||
id="autoRadioButton"
|
||||
label="Auto"
|
||||
name="themeToggleRadio"
|
||||
checked={theme === 'auto'}
|
||||
onChange={() => setConfig({ theme: 'auto' })}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Col-12>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
render(<DarkModeExample />);
|
||||
`;
|
||||
|
||||
const lightCode = `
|
||||
<Card bg='100' className="light">
|
||||
<Card.Body>
|
||||
<p className="mb-0 text-body-tertiary">
|
||||
<b>This element will retain it's color if you switch between light and dark mode.</b>
|
||||
</p>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
`;
|
||||
|
||||
const darkCode = `
|
||||
<Card bg='100' className="dark">
|
||||
<Card.Body>
|
||||
<p className="mb-0 text-body-tertiary">
|
||||
<b>This element will retain it's color if you switch between light and dark mode.</b>
|
||||
</p>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
`;
|
||||
|
||||
const dark__Code = `
|
||||
<Card bg='light' className="dark__bg-primary">
|
||||
<Card.Body>
|
||||
<p className="mb-0 dark__text-gray-100">
|
||||
<span className="fw-bold">
|
||||
The background will be primary and text color will be white in dark mode.
|
||||
</span>
|
||||
</p>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
`;
|
||||
|
||||
const DarkMode = () => {
|
||||
return (
|
||||
<div>
|
||||
<DocPageHeader title="Dark Mode">
|
||||
<p className="lead text-body-tertiary">
|
||||
It’s effortless to switch Dark Mode in {process.env.REACT_APP_TITLE}
|
||||
-React. You can enable Dark Mode by default or create a Dark/Light
|
||||
switch if you want. To set the default mode "Dark", please see the
|
||||
<Link to="/documentation/customization/configuration">
|
||||
{' '}
|
||||
configuration page
|
||||
</Link>
|
||||
</p>
|
||||
</DocPageHeader>
|
||||
<DocPagesLayout>
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header
|
||||
title="Toggle Dark Mode"
|
||||
description={`Toggling dark mode is very easy in ${process.env.REACT_APP_TITLE}-React. You can toggle dark or light mode by using checkbox, radio input, switch input and custom icon component.`}
|
||||
/>
|
||||
<PhoenixDocCard.Body
|
||||
code={darkModeExampleCode}
|
||||
noInline
|
||||
scope={{ FeatherIcon, useAppContext, ThemeToggler, ThemeDropdown }}
|
||||
/>
|
||||
</PhoenixDocCard>
|
||||
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header title="Modify Dark colors" noPreview />
|
||||
<PhoenixDocCard.Body>
|
||||
<p className="mb-0 text-body-secondary">
|
||||
You can find all the variables used to create the dark mode in
|
||||
<code> src/assets/scss/theme/root/_dark.scss </code> file. If you
|
||||
want to override a variable, copy that variable to{' '}
|
||||
<code> src/assets/scss/_user-variables.scss </code> file and
|
||||
update it as you see fit. After changing the variable build your
|
||||
scss again.
|
||||
</p>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
|
||||
<PhoenixDocCard noProvider className="mb-4">
|
||||
<PhoenixDocProvider>
|
||||
<PhoenixDocCard.Header title="Using the Dark className" noPreview />
|
||||
<PhoenixDocCard.Body>
|
||||
<h6 className="fs-8 mb-3">
|
||||
You can keep a style constant regardless of current (light or
|
||||
dark) mode
|
||||
</h6>
|
||||
<p className="mb-2">
|
||||
If you want a component to retain it’s color (light or dark) as
|
||||
it is regardless of the current mode, you can use the following
|
||||
classeNames -
|
||||
</p>
|
||||
<p className="mb-2">
|
||||
<code> .light </code> - It will keep the color light even if the
|
||||
current mode is dark
|
||||
</p>
|
||||
<p>
|
||||
<code> .dark </code> - It will keep the color dark even if the
|
||||
current mode is light
|
||||
</p>
|
||||
|
||||
<Row className="mb-5">
|
||||
<Col sm={6}>
|
||||
<PhoenixDocCard>
|
||||
<PhoenixDocCard.Header />
|
||||
<PhoenixDocCard.Body code={lightCode} />
|
||||
</PhoenixDocCard>
|
||||
</Col>
|
||||
<Col sm={6}>
|
||||
<PhoenixDocCard>
|
||||
<PhoenixDocCard.Header />
|
||||
<PhoenixDocCard.Body code={darkCode} />
|
||||
</PhoenixDocCard>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<h6 className="fs-8 mb-3">
|
||||
Override Background and Text color only for dark mode
|
||||
</h6>
|
||||
<p className="mb-2">
|
||||
If you want to use a different text color or background color
|
||||
rather than the default dark theme color for any element, you
|
||||
can use the special "dark" classeNames:
|
||||
</p>
|
||||
<ul className="mb-2">
|
||||
<li>
|
||||
<code>dark__bg-* </code>
|
||||
</li>
|
||||
<li>
|
||||
<code>dark__text-* </code>
|
||||
</li>
|
||||
</ul>
|
||||
<p>The following element illustrates the example:</p>
|
||||
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header />
|
||||
<PhoenixDocCard.Body code={dark__Code} />
|
||||
</PhoenixDocCard>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocProvider>
|
||||
</PhoenixDocCard>
|
||||
</DocPagesLayout>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DarkMode;
|
||||
287
src/pages/documentation/customization/Styling.tsx
Normal file
287
src/pages/documentation/customization/Styling.tsx
Normal file
@@ -0,0 +1,287 @@
|
||||
import PhoenixDocCard from 'components/base/PhoenixDocCard';
|
||||
import DocPageHeader from 'components/docs/DocPageHeader';
|
||||
import PhoenixLiveEditor from 'components/docs/PhoenixLiveEditor';
|
||||
import DocPagesLayout from 'layouts/DocPagesLayout';
|
||||
|
||||
const themeColorCode = `
|
||||
//*-----------------------------------------------
|
||||
//| Theme Colors
|
||||
//-----------------------------------------------*/
|
||||
|
||||
$primary: $blue !default;
|
||||
$secondary: $gray-900 !default;
|
||||
$success: $green !default;
|
||||
$info: $cyan !default;
|
||||
$warning: $yellow !default;
|
||||
$danger: $red !default;
|
||||
$light: $gray-100 !default;
|
||||
$dark: $gray-1100 !default;
|
||||
`;
|
||||
|
||||
const bodyColorCode = `
|
||||
//*-----------------------------------------------
|
||||
//| Body Colors
|
||||
//-----------------------------------------------*/
|
||||
|
||||
$body-color: $gray-900 !default;
|
||||
$body-bg: $gray-50 !default;
|
||||
|
||||
$body-secondary-color: $gray-800 !default;
|
||||
$body-secondary-bg: $gray-200 !default;
|
||||
|
||||
$body-tertiary-color: $gray-700 !default;
|
||||
$body-tertiary-bg: $gray-300 !default;
|
||||
|
||||
$body-quaternary-color: $gray-500 !default;
|
||||
$body-quaternary-bg: $gray-400 !default;
|
||||
|
||||
$body-emphasis-color: $gray-1100 !default;
|
||||
$body-emphasis-bg: $white !default;
|
||||
|
||||
$body-highlight-color: $gray-1000 !default;
|
||||
$body-highlight-bg: $gray-100 !default;
|
||||
`;
|
||||
|
||||
const darkThemeColorCode = `
|
||||
//*-----------------------------------------------
|
||||
//| Dark theme colors
|
||||
//-----------------------------------------------*/
|
||||
|
||||
$theme-colors-dark: (
|
||||
'primary': $blue-300,
|
||||
'secondary': $secondary,
|
||||
'success': $green-300,
|
||||
'info': $cyan-300,
|
||||
'warning': $orange-300,
|
||||
'danger': $red-300,
|
||||
'light': rgba(map-get($grays-dark, '200'), 0.25),
|
||||
'dark': $light
|
||||
) !default;
|
||||
|
||||
`;
|
||||
|
||||
const themeUsedColorsCode = `
|
||||
// Theme used colors
|
||||
|
||||
$theme-color-shades: (
|
||||
'primary-lighter': $blue-200,
|
||||
'primary-light': $blue-300,
|
||||
'primary-dark': $blue-600,
|
||||
'primary-darker': $blue-700,
|
||||
|
||||
'secondary-lighter': $gray-200,
|
||||
'secondary-light': $gray-300,
|
||||
'secondary-dark': $gray-1000,
|
||||
'secondary-darker': $gray-700,
|
||||
|
||||
'warning-lighter': $orange-200,
|
||||
'warning-light': $orange-300,
|
||||
'warning-dark': $orange-600,
|
||||
'warning-darker': $orange-700,
|
||||
|
||||
'danger-lighter': $red-200,
|
||||
'danger-light': $red-300,
|
||||
'danger-dark': $red-600,
|
||||
'danger-darker': $red-700,
|
||||
|
||||
'success-lighter': $green-200,
|
||||
'success-light': $green-300,
|
||||
'success-dark': $green-600,
|
||||
'success-darker': $green-700,
|
||||
|
||||
'info-lighter': $cyan-200,
|
||||
'info-light': $cyan-300,
|
||||
'info-dark': $cyan-600,
|
||||
'info-darker': $cyan-700,
|
||||
) !default;
|
||||
|
||||
|
||||
// Dark theme used color
|
||||
|
||||
$theme-color-shades-dark: (
|
||||
'primary-lighter': $blue-700,
|
||||
'primary-light': $blue-500,
|
||||
'primary-dark': $blue-300,
|
||||
'primary-darker': $blue-300,
|
||||
|
||||
'warning-lighter': $orange-700,
|
||||
'warning-light': $orange-500,
|
||||
'warning-dark': $orange-300,
|
||||
'warning-darker': $orange-300,
|
||||
|
||||
'danger-lighter': $red-700,
|
||||
'danger-light': $red-500,
|
||||
'danger-dark': $red-300,
|
||||
'danger-darker': $red-300,
|
||||
|
||||
'success-lighter': $green-700,
|
||||
'success-light': $green-500,
|
||||
'success-dark': $green-300,
|
||||
'success-darker': $green-300,
|
||||
|
||||
'info-lighter': $cyan-700,
|
||||
'info-light': $cyan-500,
|
||||
'info-dark': $cyan-300,
|
||||
'info-darker': $cyan-300,
|
||||
) !default;
|
||||
|
||||
`;
|
||||
|
||||
const usingCssVariablesCode = `
|
||||
/*-----------------------------------------------
|
||||
| Theme Styles
|
||||
-----------------------------------------------*/
|
||||
$success: #00d27a;
|
||||
$danger: #e63757;
|
||||
:root, :root.light, :root .light {
|
||||
--phoenix-primary: #{$success};
|
||||
--phoenix-primary-rgb: #{to-rgb($success)};
|
||||
...
|
||||
...
|
||||
...
|
||||
}
|
||||
[data-bs-theme="dark"]{
|
||||
--phoenix-primary: #{$danger};
|
||||
--phoenix-primary-rgb: #{to-rgb($danger)};
|
||||
.card{
|
||||
--phoenix-card-bg: #{$success};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const Styling = () => {
|
||||
return (
|
||||
<div>
|
||||
<DocPageHeader
|
||||
title="Styling"
|
||||
description="We recommend you customize your theme styles using the user style files. You can customize the theme’s styles with the following approaches:"
|
||||
/>
|
||||
<DocPagesLayout>
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header title="Edit SCSS" />
|
||||
<PhoenixDocCard.Body className="text-body-secondary">
|
||||
<p>
|
||||
You can add your own SCSS and override the theme style in the{' '}
|
||||
<code>user.scss</code> file.
|
||||
</p>
|
||||
<div className="border rounded-1 bg-body-emphasis px-3 py-2 mt-4 mb-3">
|
||||
<code>user.scss</code>
|
||||
</div>
|
||||
<p>
|
||||
To make broader changes to the design of the theme, such as
|
||||
changing the color scheme or font sizes, use{' '}
|
||||
<code>src/assets/scss/_user-variables.scss</code>. Any variable
|
||||
from <code>node_modules/bootstrap/scss/_variables.scss</code> or{' '}
|
||||
<code>src/assets/scss/theme/_variables.scss</code> can be
|
||||
overridden with your own value.
|
||||
</p>
|
||||
|
||||
<div className="border rounded-1 bg-body-emphasis px-3 py-2 mt-4 mb-3">
|
||||
<code>_user-variables.scss</code>
|
||||
</div>
|
||||
<p>
|
||||
To remove bootstrap components, update{' '}
|
||||
<code>src/scss/_bootstrap.scss</code> file.
|
||||
</p>
|
||||
<div className="border rounded-1 bg-body-emphasis px-3 py-2 mt-4 mb-3">
|
||||
<code>_bootstrap.scss</code>
|
||||
</div>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header title="Changing theme colors" />
|
||||
<PhoenixDocCard.Body className="text-body-secondary">
|
||||
<p>
|
||||
You can bring your necessary variable colors form{' '}
|
||||
<code>src/scss/theme/_colors.scss </code> and{' '}
|
||||
<code>src/scss/theme/_variables-dark.scss</code>. Paste it into{' '}
|
||||
<code> src/scss/_user-variables.scss </code> then update variables
|
||||
as your necessity. We recommend to follow this approach.
|
||||
</p>
|
||||
<p>
|
||||
Light mode is default theme style in {process.env.REACT_APP_TITLE}
|
||||
. So, if you update any bootstrap’s SCSS variables, it will effect
|
||||
in Light mode. If you want to update any color, find the
|
||||
corresponding variable for the color and place theme to
|
||||
_user-variables.scss file.
|
||||
</p>
|
||||
<PhoenixLiveEditor code={themeColorCode} />
|
||||
|
||||
<p className="mt-3">
|
||||
Most of the background and text colors used from body colors, to
|
||||
update the colors change the corresponding variables.
|
||||
</p>
|
||||
<PhoenixLiveEditor code={bodyColorCode} />
|
||||
|
||||
<p className="mt-3">
|
||||
If you want to update any theme colors for dark mode, update{' '}
|
||||
<code>$theme-colors-dark</code> variable and to update the grays
|
||||
colors you have to update the <code>$grays-dark </code>variable.
|
||||
</p>
|
||||
<PhoenixLiveEditor code={darkThemeColorCode} />
|
||||
|
||||
<h6 className="mt-4 fs-7 mb-2 fw-semibold">Theme Color Shades</h6>
|
||||
<p className="mb-1">
|
||||
All <strong>{process.env.REACT_APP_TITLE}</strong> colors are
|
||||
available as Sass variables and Sass map in{' '}
|
||||
<code>src/scss/theme/_colors.scss </code> &{' '}
|
||||
<code>src/scss/theme/_variables-dark.scss </code>file. To avoid
|
||||
increased file sizes, we don’t create text or background color
|
||||
classes for each of these variables. Instead, we choose a subset
|
||||
of these colors for a theme palette.
|
||||
</p>
|
||||
<p>
|
||||
You'll find all the colors used in the theme in a sass map name{' '}
|
||||
<code>$theme-color-shades </code>in{' '}
|
||||
<code>src/scss/theme/_colors.scss </code>file. If you want to use
|
||||
any <strong>{process.env.REACT_APP_TITLE} </strong>color to
|
||||
generate <code>text/bg </code>
|
||||
utility class, Add the color variable in{' '}
|
||||
<code>$theme-color-shades </code>map. If you want to add/change
|
||||
color for dark mode, update the{' '}
|
||||
<code>$theme-color-shades-dark </code>map.{' '}
|
||||
</p>
|
||||
<PhoenixLiveEditor code={themeUsedColorsCode} />
|
||||
<h4 className="mt-4 mb-2">Using CSS variable:</h4>
|
||||
<p>
|
||||
To update theme color with this approach, you have to update CSS
|
||||
variable for both modes. If you change any color you have to
|
||||
assign its corresponding RGB color too. Please note that sometimes
|
||||
you may need to update corresponding component's CSS variable. For
|
||||
example:
|
||||
</p>
|
||||
<PhoenixLiveEditor code={usingCssVariablesCode} />
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
|
||||
<PhoenixDocCard className="mb-4">
|
||||
<PhoenixDocCard.Header title="Compiling SCSS" />
|
||||
<PhoenixDocCard.Body>
|
||||
<p>
|
||||
Run <code>npm run build:css</code> command in your project
|
||||
directory to compile scss. This will compile all the SCSS files
|
||||
from <code>src/assets/scss/</code> directory and generate{' '}
|
||||
<code> theme.min.css </code>,<code> theme-rtl.min.css </code>,{' '}
|
||||
<code> user.min.css </code> <code> user-rtl.min.css </code>files
|
||||
in <code>public/css/</code> directory. Reload your browser to see
|
||||
the changes.
|
||||
</p>
|
||||
<p>
|
||||
<strong>
|
||||
You can also use the SCSS watcher to automatically compile and
|
||||
reload your browser every time you save your SCSS files by
|
||||
running the command
|
||||
</strong>
|
||||
<code> npm run watch:css </code>
|
||||
<strong> in a separate terminal window while running</strong>{' '}
|
||||
<code>npm start</code> <strong> in another.</strong>
|
||||
</p>
|
||||
</PhoenixDocCard.Body>
|
||||
</PhoenixDocCard>
|
||||
</DocPagesLayout>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Styling;
|
||||
67
src/pages/error/Error403.tsx
Normal file
67
src/pages/error/Error403.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import React from 'react';
|
||||
import error403Illustration from 'assets/img/spot-illustrations/403-illustration.png';
|
||||
import dark403Illustration from 'assets/img/spot-illustrations/dark403-illustration.png';
|
||||
import light403 from 'assets/img/spot-illustrations/403.png';
|
||||
import dark403 from 'assets/img/spot-illustrations/dark_403.png';
|
||||
import Button from 'components/base/Button';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import useSettingsMountEffect from 'hooks/useSettingsMountEffect';
|
||||
|
||||
const Error403 = () => {
|
||||
useSettingsMountEffect({
|
||||
disableNavigationType: true,
|
||||
disableHorizontalNavbarAppearance: true,
|
||||
disableVerticalNavbarAppearance: true,
|
||||
disableHorizontalNavbarShape: true
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<div className="px-3">
|
||||
<Row className="min-vh-100 flex-center p-5">
|
||||
<Col xs={12} xl={10} xxl={8}>
|
||||
<Row className="justify-content-center align-items-center g-5">
|
||||
<Col xs={12} lg={6} className="text-center order-lg-1">
|
||||
<img
|
||||
src={error403Illustration}
|
||||
alt=""
|
||||
width={400}
|
||||
className="img-fluid w-lg-100 d-dark-none"
|
||||
/>
|
||||
<img
|
||||
src={dark403Illustration}
|
||||
alt=""
|
||||
width={540}
|
||||
className="img-fluid w-md-50 w-lg-100 d-light-none"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} lg={6} className="text-center text-lg-start">
|
||||
<img
|
||||
src={light403}
|
||||
className="img-fluid mb-6 w-50 w-lg-75 d-dark-none"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
src={dark403}
|
||||
className="img-fluid mb-6 w-50 w-lg-75 d-light-none"
|
||||
alt=""
|
||||
/>
|
||||
<h2 className="text-body-secondary fw-bolder mb-3">
|
||||
Access Forbidden!
|
||||
</h2>
|
||||
<p className="text-body mb-5">
|
||||
You don’t have permission to access this resource.
|
||||
</p>
|
||||
<Button variant="primary" size="lg" as={Link} to="/">
|
||||
Go Home
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Error403;
|
||||
68
src/pages/error/Error404.tsx
Normal file
68
src/pages/error/Error404.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import Button from 'components/base/Button';
|
||||
import errorIllustration from 'assets/img/spot-illustrations/404-illustration.png';
|
||||
import dark404illustrations from 'assets/img/spot-illustrations/dark_404-illustration.png';
|
||||
import error404 from 'assets/img/spot-illustrations/404.png';
|
||||
import darkError40 from 'assets/img/spot-illustrations/dark_404.png';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import useSettingsMountEffect from 'hooks/useSettingsMountEffect';
|
||||
|
||||
const Error404 = () => {
|
||||
useSettingsMountEffect({
|
||||
disableNavigationType: true,
|
||||
disableHorizontalNavbarAppearance: true,
|
||||
disableVerticalNavbarAppearance: true,
|
||||
disableHorizontalNavbarShape: true
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<div className="px-3">
|
||||
<Row className="min-vh-100 flex-center p-5">
|
||||
<Col xs={12} xl={10} xxl={8}>
|
||||
<Row className="justify-content-center align-items-center g-5">
|
||||
<Col xs={12} lg={6} className="text-center order-lg-1">
|
||||
<img
|
||||
src={errorIllustration}
|
||||
alt=""
|
||||
width={400}
|
||||
className="img-fluid w-lg-100 d-dark-none"
|
||||
/>
|
||||
<img
|
||||
src={dark404illustrations}
|
||||
alt=""
|
||||
width={540}
|
||||
className="img-fluid w-md-50 w-lg-100 d-light-none"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} lg={6} className="text-center text-lg-start">
|
||||
<img
|
||||
src={error404}
|
||||
className="img-fluid mb-6 w-50 w-lg-75 d-dark-none"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
src={darkError40}
|
||||
className="img-fluid mb-6 w-50 w-lg-75 d-light-none"
|
||||
alt=""
|
||||
/>
|
||||
<h2 className="text-body-secondary fw-bolder mb-3">
|
||||
Page Missing!
|
||||
</h2>
|
||||
<p className="text-body mb-5">
|
||||
But no worries! Our ostrich is looking everywhere
|
||||
<br className="d-none d-sm-block" />
|
||||
while you wait safely.
|
||||
</p>
|
||||
<Button variant="primary" size="lg" as={Link} to="/">
|
||||
Go Home
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Error404;
|
||||
67
src/pages/error/Error500.tsx
Normal file
67
src/pages/error/Error500.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import Button from 'components/base/Button';
|
||||
import error500Illustration from 'assets/img/spot-illustrations/dark_500-illustration.png';
|
||||
import dark500Illustration from 'assets/img/spot-illustrations/500-illustration.png';
|
||||
import error500 from 'assets/img/spot-illustrations/500.png';
|
||||
import darkError500 from 'assets/img/spot-illustrations/dark_500.png';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Link } from 'react-router-dom';
|
||||
import useSettingsMountEffect from 'hooks/useSettingsMountEffect';
|
||||
|
||||
const Error500 = () => {
|
||||
useSettingsMountEffect({
|
||||
disableNavigationType: true,
|
||||
disableHorizontalNavbarAppearance: true,
|
||||
disableVerticalNavbarAppearance: true,
|
||||
disableHorizontalNavbarShape: true
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<div className="px-3">
|
||||
<Row className="min-vh-100 flex-center p-5">
|
||||
<Col xs={12} xl={10} xxl={8}>
|
||||
<Row className="justify-content-center g-5">
|
||||
<Col xs={12} lg={6} className="text-center order-lg-1">
|
||||
<img
|
||||
src={error500Illustration}
|
||||
alt=""
|
||||
width={400}
|
||||
className="img-fluid w-md-50 w-lg-100 d-dark-none"
|
||||
/>
|
||||
<img
|
||||
src={dark500Illustration}
|
||||
alt=""
|
||||
width={540}
|
||||
className="img-fluid w-lg-100 d-light-none"
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={12} lg={6} className="text-center text-lg-start">
|
||||
<img
|
||||
src={error500}
|
||||
className="img-fluid mb-6 w-50 w-lg-75 d-dark-none"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
src={darkError500}
|
||||
className="img-fluid mb-6 w-50 w-lg-75 d-light-none"
|
||||
alt=""
|
||||
/>
|
||||
<h2 className="text-body-secondary fw-bolder mb-3">
|
||||
Internal Error!
|
||||
</h2>
|
||||
<p className="text-body mb-5">
|
||||
Uh-oh! It seems like our server is taking an unexpected coffee
|
||||
break.
|
||||
</p>
|
||||
<Button variant="primary" size="lg" as={Link} to="/">
|
||||
Go Home
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Error500;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user