133 lines
5.2 KiB
TypeScript
133 lines
5.2 KiB
TypeScript
/* -------------------------------------------------------------------------- */
|
|
/* Libraries */
|
|
/* -------------------------------------------------------------------------- */
|
|
import React, { useEffect, useState } from "react";
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Components */
|
|
/* -------------------------------------------------------------------------- */
|
|
import ServiceComponent from "components/containers/ServiceComponent";
|
|
import Switch from "components/controls/Switch";
|
|
import TextAction from "components/controls/TextAction";
|
|
import ThinSingleColumn from "components/layouts/ThinSingleColumn";
|
|
import { useServicesStore } from "services/data/servicesSlice";
|
|
import { useServicesViewModel } from "services/controller/servicesViewModel";
|
|
import _ from "lodash";
|
|
import { useUIStore } from "ui/data/uiSlice";
|
|
import { useSubscriptionsStore } from "subscriptions/data/subscriptionsSlice";
|
|
import { useSubscriptionsViewModel } from "subscriptions/controller/subscriptionsViewModel";
|
|
import { Service } from "services/domain/serviceEntity";
|
|
import PasswordConfirmation from "user/views/PasswordConfirmation";
|
|
import CircleLoader from "components/CircleLoader";
|
|
import Failure from "core/failure";
|
|
/* -------------------------------------------------------------------------- */
|
|
/* Component */
|
|
/* -------------------------------------------------------------------------- */
|
|
const Services = () => {
|
|
const [password, setPassword] = useState<string | null>();
|
|
const [confirmShown, toggleConfirm] = useState(false);
|
|
const [selectedService, setSelectedService] = useState<
|
|
Service["id"] | null
|
|
>();
|
|
/* ---------------------------------- Store --------------------------------- */
|
|
const servicesStore = useServicesStore();
|
|
const uiStore = useUIStore();
|
|
const subscriptionsStore = useSubscriptionsStore();
|
|
const { services, isLoading, loadServices } = useServicesViewModel({
|
|
...servicesStore,
|
|
notify: uiStore.notify,
|
|
});
|
|
const { hasSubscription, subscribe, processingSubscription } =
|
|
useSubscriptionsViewModel(subscriptionsStore, uiStore);
|
|
/* ---------------------------------- Hooks --------------------------------- */
|
|
useEffect(() => {
|
|
loadServices();
|
|
}, [loadServices]);
|
|
|
|
useEffect(() => {
|
|
if(!selectedService || password) return;
|
|
toggleConfirm(true);
|
|
}, [selectedService, password]);
|
|
|
|
useEffect(() => {
|
|
if (!selectedService) {
|
|
return;
|
|
}
|
|
if (hasSubscription(selectedService)) {
|
|
return;
|
|
}
|
|
if (!password) {
|
|
return;
|
|
}
|
|
if (password !== null) {
|
|
subscribe(selectedService, password!)?.catch((failure) => {
|
|
if(Failure.isFailure(failure) && failure.status === 403) {
|
|
setPassword(null);
|
|
}
|
|
});
|
|
setSelectedService(null);
|
|
}
|
|
}, [selectedService, hasSubscription, subscribe, password]);
|
|
|
|
const handleSubscription = (serviceId: Service["id"]) => {
|
|
setSelectedService(serviceId);
|
|
};
|
|
/* --------------------------------- Markup --------------------------------- */
|
|
return (
|
|
<ThinSingleColumn>
|
|
<div className="space-y-8">
|
|
{!services?.length || isLoading
|
|
? _.times(3, (number) => (
|
|
<ServiceComponent key={number} variant="gray" clipText="tch">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<div className="text-lg font-bold">Techpal</div>
|
|
<TextAction variant="gray">about service</TextAction>
|
|
</div>
|
|
<div>
|
|
<Switch enabled={false} onChange={() => null} />
|
|
</div>
|
|
</div>
|
|
</ServiceComponent>
|
|
))
|
|
: services!.map((item, index) => {
|
|
return (
|
|
<ServiceComponent
|
|
key={index}
|
|
variant={item.variant ?? "gray"}
|
|
clipText={item.shortName}
|
|
>
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<div className="text-lg font-bold">{item.name}</div>
|
|
<TextAction variant="gray">about service</TextAction>
|
|
</div>
|
|
<div>
|
|
{processingSubscription(item.id) ? (
|
|
<div className="h-6 w-6">
|
|
<CircleLoader />
|
|
</div>
|
|
) : (
|
|
<Switch
|
|
enabled={hasSubscription(item.id)}
|
|
onChange={() => handleSubscription(item.id)}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</ServiceComponent>
|
|
);
|
|
})}
|
|
</div>
|
|
{confirmShown && selectedService && (
|
|
<PasswordConfirmation
|
|
onSubmit={(p) => setPassword(p)}
|
|
isShown={true}
|
|
onClose={() => toggleConfirm(false)}
|
|
/>
|
|
)}
|
|
</ThinSingleColumn>
|
|
);
|
|
};
|
|
|
|
export default Services;
|